![](/img/trans.png)
[英]Spring @Transactional is applied both as a dynamic Jdk proxy and an aspectj aspect
[英]@Transactional not applied with AspectJ
我決定使用AspectJ
來避免使用@Transactional
注釋的方法不能從同一個類中調用的事實
所以我添加了這個配置:
@Configuration
@EnableTransactionManagement(mode= AdviceMode.ASPECTJ)
@EnableLoadTimeWeaving(aspectjWeaving= AspectJWeaving.ENABLED)
public class App implements LoadTimeWeavingConfigurer {
@Override
public LoadTimeWeaver getLoadTimeWeaver() {
return new InstrumentationLoadTimeWeaver();
}
}
在build.gradle
runtimeOnly("org.aspectj:aspectjweaver:1.9.7")
我使用-javaagent:C:\\xx\\xx\\.m2\\repository\\org\\springframework\\spring-instrument-5.3.12.jar
運行應用程序(嵌入了 tomcat 的 Spring Boot 應用程序)
但是當我嘗試
public void m1() {
this.m2()
}
@Transactional(propagation = Propagation.REQUIRED)
public void m2() {
....
}
似乎m2()
方法不在事務中執行,
在使用這些日志記錄級別進行調試時的日志中:
logging.level.org.springframework.transaction.interceptor=trace
logging.level.org.springframework.orm.jpa=trace
沒有這樣的行:
Creating new transaction with name [xxx.m2]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
我在那里錯過了什么嗎?
我克隆了你的 GitHub 項目,然后添加
implementation 'org.springframework:spring-instrument'
implementation 'com.oracle.database.jdbc:ojdbc8:12.2.0.1'
我添加的ojdbc8
只是因為 AspectJ weaver 崩潰並且由於缺少依賴關系而在沒有它的情況下編寫核心轉儲。 如果 Spring 檢測庫引用了一個實際上不是依賴項的類,那么它一定有問題。
然后我使用 Spring 檢測和 AspectJ weaver 代理啟動了應用程序。 只有前者不足以啟動儀器,我需要兩個代理。 因為在 JDK 16+ 上,您需要將java.lang
包打開到未命名的模塊才能應用 LTW 並且我在最近的 JDK 上進行測試,所以我還添加了相應的--add-opens
選項(直到JDK 15):
--add-opens java.base/java.lang=ALL-UNNAMED
-javaagent:.../aspectjweaver-1.9.7.jar
-javaagent:.../spring-instrument-5.3.12.jar
然后一切正常:
o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
com.example.aspectj.AspectjApplication : Started AspectjApplication in 7.339 seconds (JVM running for 10.046)
com.example.aspectj.AspectjApplication : running ..
com.example.aspectj.services.FooService : m1 : called
o.s.orm.jpa.JpaTransactionManager : Creating new transaction with name [com.example.aspectj.services.BooService.m3]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
o.s.orm.jpa.JpaTransactionManager : Opened new EntityManager [SessionImpl(1516190088<open>)] for JPA transaction
o.s.orm.jpa.JpaTransactionManager : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@543f6ccb]
com.example.aspectj.services.BooService : m3 : called
o.s.orm.jpa.JpaTransactionManager : Initiating transaction commit
o.s.orm.jpa.JpaTransactionManager : Committing JPA transaction on EntityManager [SessionImpl(1516190088<open>)]
o.s.orm.jpa.JpaTransactionManager : Closing JPA EntityManager [SessionImpl(1516190088<open>)] after transaction
o.s.orm.jpa.JpaTransactionManager : Creating new transaction with name [com.example.aspectj.services.FooService.m2]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
o.s.orm.jpa.JpaTransactionManager : Opened new EntityManager [SessionImpl(45178615<open>)] for JPA transaction
o.s.orm.jpa.JpaTransactionManager : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@20e4fce0]
com.example.aspectj.services.FooService : m2 : called
o.s.orm.jpa.JpaTransactionManager : Initiating transaction commit
o.s.orm.jpa.JpaTransactionManager : Committing JPA transaction on EntityManager [SessionImpl(45178615<open>)]
o.s.orm.jpa.JpaTransactionManager : Closing JPA EntityManager [SessionImpl(45178615<open>)] after transaction
我的理解是,如果您有一個 bean fooService
,並且您在fooService
上調用了一個方法m1
,並且這不會創建事務,因此當您調用另一個方法時不會創建任何事務,在這種情況下是m2
,這是預期的行為。
如果您以相反的方式這樣做,則會創建一個事務,如: m2
調用m1
。 我之所以知道這一點,是因為我們在項目中遇到了同樣的問題,這非常令人困惑。 不知道為什么會這樣,我試圖尋找有關此的文檔,如果找到它,我會將其添加到我的答案中。 總之,事務只能通過在 bean 外部調用 bean 上的@Transactional
方法來創建,而不能由 bean 本身通過另一個非事務方法創建。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.