[英]Spring Boot + AspectJ: why code must be compiled twice, before transactions start working?
我正在使用帶有 AspectJ 1.9.7 (CTW) 的 Spring 引導 2.5.5。 我發現有時事務不會回滾,要解決這個問題,我只需要重新編譯代碼並再次運行它。 例如:
我有方法 addB() 持久化實體 B,方法 addC() 拋出異常和方法 A() 組合它們。 當我調用 A() 時,拋出異常,但實體 B 保留在數據庫中(如預期的那樣)。 當我用 @Transactional 注釋方法 A() 時,結果是相同的。 但是,如果我再次構建所有內容(沒有任何更改),那么事務將被回滾並且數據庫中沒有新記錄。
這是我的完整 POM:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.abcc</groupId>
<artifactId>abcc</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>abcc</name>
<description>abcc</description>
<properties>
<java.version>11</java.version>
<log4j2.version>2.15.0</log4j2.version>
<aspectj.version>1.9.7</aspectj.version>
<aspectj-maven-plugin.version>1.14.0</aspectj-maven-plugin.version>
</properties>
<dependencies>
<!--SPRING-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!--CACHE-->
<dependency>
<groupId>javax.cache</groupId>
<artifactId>cache-api</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>3.8.1</version>
</dependency>
<!--DATABASE-->
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.18.1</version>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.19.Final</version>
</dependency>
<dependency>
<groupId>org.passay</groupId>
<artifactId>passay</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>2.4.2</version>
</dependency>
<dependency>
<groupId>com.sanctionco.jmail</groupId>
<artifactId>jmail</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.10.13</version>
</dependency>
<!--AOP-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
<profiles>
<profile>
<id>dev</id>
<properties>
<activatedProperties>dev</activatedProperties>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>test</id>
<properties>
<activatedProperties>test</activatedProperties>
</properties>
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.191</version>
</dependency>
</dependencies>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
<excludeDevtools>false</excludeDevtools>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<trimStackTrace>false</trimStackTrace>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>${aspectj-maven-plugin.version}</version>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<configuration>
<showWeaveInfo>true</showWeaveInfo>
<Xlint>ignore</Xlint>
<verbose>true</verbose>
<source>${java.version}</source>
<target>${java.version}</target>
<complianceLevel>${java.version}</complianceLevel>
<encoding>utf-8</encoding>
<outxml>true</outxml>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
<forceAjcCompile>true</forceAjcCompile>
<sources/>
<weaveDirectories>
<weaveDirectory>${project.build.outputDirectory}</weaveDirectory>
</weaveDirectories>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>
這是非常奇怪的情況,我找不到相關信息。 你能幫忙找出原因嗎?
這是一個臨時答案,因為評論太有限,無法解釋我對 MCVE 的體驗。
我無法重現該問題,因為 IDEA 沒有找到 Lombok 設置器。 即使在運行之前將構建操作委托給 Maven,我也會得到NoSuchMethodError: '...TestEntity.setCode(java.lang.String)'
。 接下來,我將嘗試不使用 Lombok。 請注意,Lombok 和 AspectJ 不能互相配合,請在此處查看我的回答。 或者,您也可以確保 Maven 執行以下任一操作:
我在 IDE 中生成了構造函數、getter 和 setter,而不是使用 Lombok。 現在項目在 IDE 和 Maven 中編譯。 它的行為與應有的完全一樣。 使用@Transactional
,創建 0 個實體,沒有它 2。
我不確定 Lombok 與 AspectJ 是否真的是由於使用 Lombok 注釋時的不可編譯性而導致的問題,但在沒有 Lombok 的情況下嘗試應該很容易。 如果它也適用於您的環境,我們找到了罪魁禍首,可以考慮實施上述 3 種方法之一。 然后你可以告訴我你這樣做是否有任何困難。
首先:您的多模塊方法在我的環境中完美運行。 但是后來我檢查了初始的 MCVE,當我完全刪除 Lombok 時,奇怪的行為並沒有消失。 在閱讀您的答案( 這個)時,我在 IntelliJ 設置(構建工具-> Z9115C10980645C41313F244AC1A37F和它應該開始工作)中檢查了“ Delegate IDE 構建/運行對 maven 的操作”。 在下一步中,我關閉了此選項並在運行配置中選中了“運行前不要構建”。 我不完全理解它(特別是為什么它在第二次嘗試后以舊方式工作),但你的評論幫助我實現了這一點。
我將研究 IntelliJ 行為(在兩種情況下,控制台 output 幾乎相同),但如果您知道它為什么會這樣工作,我會很高興聽到它。 你幫了我很多,謝謝!
摘要解決方案:我在我的應用程序的 IntelliJ 運行配置中啟用了“運行前不要構建”。 現在更改在第一次構建后起作用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.