簡體   English   中英

定制彈簧AOP周圍+ @Transactional

[英]Custom Spring AOP Around + @Transactional

我有一個自定義周圍實現匹配自定義注釋。 我希望自定義在外部@Transactional中執行。 不幸的是,這似乎不起作用。 (AOP正在工作。我看到展示它的堆棧跟蹤)。

堆棧跟蹤顯示我的AOP執行之前(記錄器),MyBatis會話啟動事務,MyBatis關閉事務,Spring關閉事務,然后我的AOP完成。

我認為讓我的AOP工具Ordered會有所幫助。 我將返回的值設置為1.我用過。 這沒用。 我想這是因為我誤讀了Spring的命令。

建議訂購

當多條建議都想在同一個連接點運行時會發生什么? Spring AOP遵循與AspectJ相同的優先級規則來確定建議執行的順序。 最高優先級的建議首先“在路上”(所以給出兩條之前的建議,優先級最高的建議先運行)。 從連接點“出路”,最高優先級建議最后運行(因此,給出兩條后建議,具有最高優先級的建議將運行第二)。

當在不同方面定義的兩條建議都需要在同一個連接點運行時,除非您另行指定,否則執行順序是未定義的。 您可以通過指定優先級來控制執行順序。 這是通過在方法類中實現org.springframework.core.Ordered接口或使用Order注釋對其進行注釋來以常規Spring方式完成的。 給定兩個方面,從Ordered.getValue()(或注釋值)返回較低值的方面具有較高的優先級。

當在同一方面定義的兩條建議都需要在同一個連接點上運行時,排序是未定義的(因為沒有辦法通過反射為javac編譯的類檢索聲明順序)。 考慮將這些建議方法折疊到每個方面類中每個連接點的一個建議方法中,或者將這些建議重構為單獨的方面類 - 可以在方面級別進行排序。

所以我拿出了order屬性。 這應該使@Transactional返回Integer.MIN_VALUE。 因此,如果我理解上面的引用,它應該運行到最后。 當我重新部署時,它仍然向后執行。 我的AOP,Spring TX,MyBatis,關閉MyBatis,關閉SPring Tx,關閉我的AOP。

我究竟做錯了什么?

如果訂單屬性未配置為@Transactional注解,那么顧問 ,負責事務屬性- AbstractPointcutAdvisor (事實上,它的子類之一)將返回有序 .LOWEST_PRECEDENCE,它被定義為Integer.MAX_VALUE的。

負責自定義AOP建議的Advisor是同一AbstractPointcutAdvisor的子類,它將查看實際的Advice是否實現了Ordered接口,如果是,則在排序期間將使用提供的值。 如果自定義AOP建議未實現Ordered接口,則Advisor返回相同的默認Ordered.LOWEST_PRECEDENCE,並且排序結果變得有些不可預測。

因此,為@Transactional注釋配置order屬性,例如像這樣

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
           http://www.springframework.org/schema/tx 
           http://www.springframework.org/schema/tx/spring-tx-3.1.xsd>
           .......

           <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" order="[Order for @Transactional]">
<beans/>    

並且您的自定義AOP建議實現如下所示

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

import org.springframework.core.Ordered;

@Aspect
public class CustomAspect implements Ordered {

    @Around(value = "@annotation(CustomAnnotation)")
    public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
    ... 
    }
    ....

    @Override
    public int getOrder() { 
        return [Order for @CustomAnnotation];
    }

    ....

}

然后你可能擁有整個應用程序中的排序的所有自由(但靜態)。

幕后 ,它是AspectJAwareAdvisorAutoProxyCreator ,它在代理初始化時使用比較器org.springframework.aop.aspectj.autoproxy.AspectJPrecedenceComparator對Advisors進行排序,該比較器將排序委托給OrderComparator 稍后,在實際執行時, AopProxy的具體實現為特定方法提供了一個建議數組,它稱之為攔截器,這可能用於動態重新排序,我猜,但這些東西都不容易在我看來可訪問和/或可配置。

我的環境是Spring Beans,TX,AOP - 所有版本4.0.3。 我還有兩個自定義事務管理器,一個是Hibernate綁定的,一個是JDBC DataSource綁定的,但我認為這不重要

經過一些實驗后發現,簡單地刪除訂單屬性並不能使其工作。 我覺得這很奇怪,因為@Transactional默認順序是Integer.MIN_VALUE 顯然,如果要啟用排序,則必須將訂單明確設置為所有AOP訂單中的最小訂單。

從頁面https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html ,它表示事務的默認順序是Ordered.LOWEST_PRECEDENCE ,其值等於Integer.MAX_VALUE

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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