簡體   English   中英

@Transactional 不適用於 AspectJ

[英]@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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM