Spring mode = "aspectj" 配置事務報錯
阿新 • • 發佈:2019-02-09
程式碼環境
Spring4.3.7 + Hibernate5.1.4 + Jpa
意圖
配置宣告式事務.
Spring 事務管理中, 開啟註解驅動< tx:annotation-driven />
問題
使用預設基於代理的方式配置, 事務生效, 想要使用基於aspectj 模式, 配置, Service程式碼都無誤, 但是就是報錯.
jars :
- spring-aspects
- spring-aspects
- aspectjrt
<tx:annotation-driven transaction-manager="transactionManager" mode="aspectj" />
錯誤資訊
javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:282 )
at com.sun.proxy.$Proxy33.persist(Unknown Source)
血淚
跟蹤程式碼發現, EntityManager 拿不到事務, 卻想做persist 操作, spring 換成4.0.0, 不會報錯, 但是事務無效, 不會真正執行儲存操作, 這個問題折磨了我好幾天, 最後終於從同事那兒get 到.
原因
點開mode=”aspectj”, 發現Spring有這麼一段
AspectJ weaving requires spring-aspects.jar on the classpath,
as well as load-time weaving (or compile-time weaving) enabled.
也就是說使用spring-aspects.jar 的aspectj, 需要指定編織時間, 使用編譯時織入.
aspectj 是靜態織入的, 也就是編譯期織入、類載入期織入(LTW), 編譯期織入可以採用編輯器(maven, ant)等工具, 類載入器可以通過類載入器,在類位元組碼載入到JVM時,織入切面.
這裡提供通過maven,指定spring-aspectj通過編譯時織入事務程式碼, 在pom.xml新增
<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>
<configuration>
<complianceLevel>1.8</complianceLevel>
<source>1.8</source>
<target>1.8</target>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
編譯完成後, 在class檔案可以看到 service 中加入以下程式碼
AnnotationTransactionAspect var10000 = AnnotationTransactionAspect.aspectOf();
...
var10000.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96c(this, new UserService$AjcClosure1(var4), ajc$tjp_0);
這就是aspectj自動完成程式碼編織, 加入事務管理.
做插入修改,操作,無誤,不再報錯…
後續再出現異常繼續發在這裡, 未完待續…