天天看點

SpringAOP通知細節-避坑指南

文章目錄

  • ​​1.Spring基于XML的通知執行順序​​
  • ​​1.1.XML檔案配置說明​​
  • ​​1.2.各種通知說明​​
  • ​​1.3.在配置同一個切入點且不出現異常時的執行順序​​
  • ​​1.4.情況一​​
  • ​​1.2.情況二​​
  • ​​1.3.情況三​​
  • ​​1.4.情況四​​
  • ​​1.5.小結​​
  • ​​2.Spring基于注解的通知執行順序​​
  • ​​2.1.正常情況​​
  • ​​2.2.異常情況​​
  • ​​2.3.探究順序錯誤的真相​​
  • ​​2.4.結論​​

1.Spring基于XML的通知執行順序

1.1.XML檔案配置說明

圖檔來源:《Java EE企業級應用開發教程》

SpringAOP通知細節-避坑指南

1.2.各種通知說明

配置前置通知:在切入點方法執行之前執行

配置後置通知(傳回通知):在切入點方法正常執行之後執行。它和異常通知永遠隻能執行一個

配置異常通知:在切入點方法執行産生異常之後執行。它和後置通知永遠隻能執行一個

配置最終通知:無論切入點方法是否正常執行,它都會在其後面執行

配置環繞通知:可以在代碼中手動控制增強方法何時執行

注意:後置通知和最終通知的差別:後置通知時在方法成功執行後會執行的,如果出現異常就不執行。而最終通知時無論是否出現異常都會執行的,感覺類似于finally

1.3.在配置同一個切入點且不出現異常時的執行順序

SpringAOP通知細節-避坑指南
注意,橢圓中順序不固定,具體順序與配置檔案的申明順序有關

1.4.情況一

<!--3.2.配置通知-->
 <aop:aspect ref="tx">
     <!--前置通知-->
     <aop:before method="openTx" pointcut-ref="pointcut"/>
     <!--環繞通知-->
     <aop:around method="aroundAdvice" pointcut-ref="pointcut"/>
     <!--後置通知(傳回通知)-->
     <aop:after-returning method="CommitTx" pointcut-ref="pointcut" returning="value"/>
     <!--最終通知-->
     <aop:after method="finnallyMethod" pointcut-ref="pointcut"/>
     <!--異常通知-->
     <aop:after-throwing method="Rollback" pointcut-ref="pointcut" throwing="ex"/>
 </aop:aspect>      

順序:

SpringAOP通知細節-避坑指南

1.2.情況二

<!--3.2.配置通知-->
 <aop:aspect ref="tx">
     <!--環繞通知-->
     <aop:around method="aroundAdvice" pointcut-ref="pointcut"/>
     <!--前置通知-->
     <aop:before method="openTx" pointcut-ref="pointcut"/>
     <!--後置通知(傳回通知)-->
     <aop:after-returning method="CommitTx" pointcut-ref="pointcut" returning="value"/>
     <!--最終通知-->
     <aop:after method="finnallyMethod" pointcut-ref="pointcut"/>
     <!--異常通知-->
     <aop:after-throwing method="Rollback" pointcut-ref="pointcut" throwing="ex"/>
 </aop:aspect>      

順序:

SpringAOP通知細節-避坑指南
結論一:前置通知和環繞通知的順序和申明順序有關,申明在前的先執行

1.3.情況三

<aop:aspect ref="tx">
    <!--環繞通知-->
    <aop:around method="aroundAdvice" pointcut-ref="pointcut"/>
    <!--前置通知-->
    <!--<aop:before method="openTx" pointcut-ref="pointcut"/>-->
    <!--後置通知(傳回通知)-->
    <aop:after-returning method="CommitTx" pointcut-ref="pointcut" returning="value"/>
    <!--最終通知-->
    <aop:after method="finnallyMethod" pointcut-ref="pointcut"/>
    <!--異常通知-->
    <aop:after-throwing method="Rollback" pointcut-ref="pointcut" throwing="ex"/>
</aop:aspect>      

順序:

SpringAOP通知細節-避坑指南

1.4.情況四

<aop:aspect ref="tx">
    <!--環繞通知-->
    <aop:around method="aroundAdvice" pointcut-ref="pointcut"/>
    <!--前置通知-->
    <!--<aop:before method="openTx" pointcut-ref="pointcut"/>-->
    <!--最終通知-->
    <aop:after method="finnallyMethod" pointcut-ref="pointcut"/>
    <!--後置通知(傳回通知)-->
    <aop:after-returning method="CommitTx" pointcut-ref="pointcut" returning="value"/>
    <!--異常通知-->
    <aop:after-throwing method="Rollback" pointcut-ref="pointcut" throwing="ex"/>
</aop:aspect>      

順序:

SpringAOP通知細節-避坑指南

1.5.小結

結論:Spring基于XML的申明式通知的執行順序與配置檔案中的申明順序有關

2.Spring基于注解的通知執行順序

SpringAOP通知細節-避坑指南

我們在網上查找關于SpringAop執行順序的的資料,大多數時候,你會查到如下的答案:

2.1.正常情況

SpringAOP通知細節-避坑指南

2.2.異常情況

SpringAOP通知細節-避坑指南
上述測試結果是在Spring的5.2.6.RELEASE版本下進行測試,換成5.2.7.RELEASE版本測試結果就不同了!

2.3.探究順序錯誤的真相

于是去官網搜尋文檔,不得不說Spring由于過于龐大,官網的文檔已經到了冗雜的地步,不過最終還是找到了:

​​https://docs.spring.io/spring-framework/docs/5.2.9.RELEASE/spring-framework-reference/core.html#aop-ataspectj-advice-ordering​​​

SpringAOP通知細節-避坑指南

As of Spring Framework 5.2.7, advice methods defined in the same @Aspect class that need to run at the same join point are assigned precedence based on their advice type in the following order, from highest to lowest precedence: @Around, @Before, @After, @AfterReturning, @AfterThrowing.

翻譯重點:

從Spring5.2.7開始,在相同@Aspect類中,通知方法将根據其類型按照從高到低的優先級進行執行:@Around,@Before ,@After,@AfterReturning,@AfterThrowing。

2.4.結論