天天看點

@Order屬性與通知執行先後順序

申明:本文轉載至https://www.cnblogs.com/zjrodger/p/5633922.html,如有侵權,請及時告知,本人将立即删除。

【障礙再現】

    MyBatis配置多資料源時,資料源切換失敗。

【原因分析】

    自定義切面和Spring自帶事務切面“即<aop:advisor>”執行的先後順序導緻資料源不能切換成功。

【解決方案】

1、配置代碼

1 <aop:config>                    
2     <!-- 1、Spring架構自身提供的切面 -->
3     <aop:advisor advice-ref="userTxAdvice" pointcut="execution(public * com.zjrodger.*.service..*.*(..))" order="2"/>                                
4     <!-- 2、使用者自定義的切面,根據切入點,動态切換資料源。 -->        
5     <aop:aspect id="dataSourceAspect" ref="dataSourceInterceptor" order="1">                                        
6         <aop:before method="setdataSourceBakDb"  pointcut="execution(* com.zjrodger.bakdata.service..*.*(..))"/>                        
7         <aop:before method="setdataSourceHuihangDb"  pointcut="execution(* com.zjrodger.datatobank.service..*.*(..))"/>    
8     </aop:aspect>        
9 </aop:config>      

2、說明

    在AOP中,當執行同一個切入點時,不同切面的執行先後順序是由“每個切面的order屬性”而定的,order越小,則該該切面中的通知越先被執行。

上述<aop:config>元素中,引用了兩個切面類:“userTxAdvice類”和“dataSourceAspect類”,其中<aop:advisor>是Spring架構自定義的切面标簽。

根據兩個切面類order屬性的定義,當程式執行時并且觸發切入點後(即調用

com.zjrodger.bakdata.service包及其子包下的方法),dataSourceAspect切面類中的setdatasourceBakDb()方通知法首先執行,之後才會執行userTxAdvice事務類中的相關通知方法。

【拓展】

若不想設定Order屬性,如何能決定不同切面類中通知執行的先後順序?

答:可以調整,在不定義Order屬性的前提下,可以通過切面類的定義順序來決定通知執行的先後順序。

    但需要特别注意的是,若<aop:config>元素中同時存在“<aop:advisor>”元素和“<aop:aspect>元素”(“<aop:pointcut>元素” 可有可無),則它們元素必須按照< aop:pointcut >,<aop:advisor>和<aop:aspect>此順序來定義。

    正因為“<aop:advisor>”元素和“<aop:aspect>元素”定義順序是不能調整的,進而導緻在沒有指定 “order屬性”的前提下,“<aop:advisor>”元素對應切面類中通知的執行順序優先于“<aop:aspect>元素” 對應切面類中通知的執行。

    此時,隻能通過指定Order屬性來調整這兩個切面類中通知執行的先後順序了。

【結論】

(1)在AOP中,當執行同一個切入點時,不同切面的執行先後順序是由“每個切面的order屬性”而定的,order越小,則該該切面中的通知越先被執行。

(2)不定義Order屬性,通過切面類的定義順序來決定通知執行的先後順序

若不同切面類執行時,在沒有定義“order屬性”,而且切面類中觸發增強通知的切入點都相同,則在切面類中的通知的執行順序與該切面類在<aop:config>元素中“聲明的順序”相關,即先聲明的切面類先執行,後聲明的切面類後執行