spring多個AOP執行先后順序


眾所周知,spring聲明式事務是基於AOP實現的,那么,如果我們在同一個方法自定義多個AOP,我們如何指定他們的執行順序呢?

網上很多答案都是指定order,order越小越是最先執行,這種也不能算是錯,但有些片面。

 

  • 配置AOP執行順序的三種方式:

 

  1. 通過實現org.springframework.core.Ordered接口
    [java]  view plain  copy
     
     
     
    1. @Component  
    2. @Aspect  
    3. @Slf4j  
    4. public class MessageQueueAopAspect1 implements Ordered{@Override  
    5.     public int getOrder() {  
    6.         // TODO Auto-generated method stub  
    7.         return 2;  
    8.     }  
    9.       
    10. }  
  2. 通過注解
    [java]  view plain  copy
     
     
     
    1. @Component  
    2. @Aspect  
    3. @Slf4j  
    4. @Order(1)  
    5. public class MessageQueueAopAspect1{  
    6.       
    7.     ...  
    8. }  
  3. 通過配置文件配置
    [html]  view plain  copy
     
     
     
    1. <aop:config expose-proxy="true">  
    2.     <aop:aspect ref="aopBean" order="0">    
    3.         <aop:pointcut id="testPointcut"  expression="@annotation(xxx.xxx.xxx.annotation.xxx)"/>    
    4.         <aop:around pointcut-ref="testPointcut" method="doAround" />    
    5.         </aop:aspect>    
    6. </aop:config>  

我們在同一個方法上加以下兩個AOP,看看究竟。

 

[java]  view plain  copy
 
 
 
  1. @Component  
  2. @Aspect  
  3. @Slf4j  
  4. public class MessageQueueAopAspect1 implements Ordered{  
  5.       
  6.     @Resource(name="actionMessageProducer")  
  7.     private IProducer<MessageQueueInfo> actionProducer;     
  8.       
  9.     @Pointcut("@annotation(com.xxx.annotation.MessageQueueRequire1)")  
  10.     private void pointCutMethod() {  
  11.     }  
  12.       
  13.     //聲明前置通知  
  14.     @Before("pointCutMethod()")  
  15.     public void doBefore(JoinPoint point) {  
  16.         log.info("MessageQueueAopAspect1:doBefore");  
  17.         return;  
  18.     }  
  19.   
  20.     //聲明后置通知  
  21.     @AfterReturning(pointcut = "pointCutMethod()", returning = "returnValue")  
  22.     public void doAfterReturning(JoinPoint point,Object returnValue) {  
  23.         log.info("MessageQueueAopAspect1:doAfterReturning");  
  24.     }  
  25.   
  26.     //聲明例外通知  
  27.     @AfterThrowing(pointcut = "pointCutMethod()", throwing = "e")  
  28.     public void doAfterThrowing(Exception e) {  
  29.         log.info("MessageQueueAopAspect1:doAfterThrowing");  
  30.     }  
  31.   
  32.     //聲明最終通知  
  33.     @After("pointCutMethod()")  
  34.     public void doAfter() {  
  35.         log.info("MessageQueueAopAspect1:doAfter");  
  36.     }  
  37.   
  38.     //聲明環繞通知  
  39.     @Around("pointCutMethod()")  
  40.     public Object doAround(ProceedingJoinPoint pjp) throws Throwable {  
  41.         log.info("MessageQueueAopAspect1:doAround-1");  
  42.         Object obj = pjp.proceed();  
  43.         log.info("MessageQueueAopAspect1:doAround-2");  
  44.         return obj;  
  45.     }  
  46.       
  47.     @Override  
  48.     public int getOrder() {  
  49.         return 1001;  
  50.     }  
  51. }  
[java]  view plain  copy
 
 
 
  1. @Component  
  2. @Aspect  
  3. @Slf4j  
  4. public class MessageQueueAopAspect2 implements Ordered{  
  5.       
  6.     @Resource(name="actionMessageProducer")  
  7.     private IProducer<MessageQueueInfo> actionProducer;     
  8.       
  9.     @Pointcut("@annotation(com.xxx.annotation.MessageQueueRequire2)")  
  10.     private void pointCutMethod() {  
  11.     }  
  12.       
  13.       
  14.     //聲明前置通知  
  15.     @Before("pointCutMethod()")  
  16.     public void doBefore(JoinPoint point) {  
  17.         log.info("MessageQueueAopAspect2:doBefore");  
  18.         return;  
  19.     }  
  20.   
  21.     //聲明后置通知  
  22.     @AfterReturning(pointcut = "pointCutMethod()", returning = "returnValue")  
  23.     public void doAfterReturning(JoinPoint point,Object returnValue) {  
  24.         log.info("MessageQueueAopAspect2:doAfterReturning");  
  25.     }  
  26.   
  27.     //聲明例外通知  
  28.     @AfterThrowing(pointcut = "pointCutMethod()", throwing = "e")  
  29.     public void doAfterThrowing(Exception e) {  
  30.         log.info("MessageQueueAopAspect2:doAfterThrowing");  
  31.     }  
  32.   
  33.     //聲明最終通知  
  34.     @After("pointCutMethod()")  
  35.     public void doAfter() {  
  36.         log.info("MessageQueueAopAspect2:doAfter");  
  37.     }  
  38.   
  39.     //聲明環繞通知  
  40.     @Around("pointCutMethod()")  
  41.     public Object doAround(ProceedingJoinPoint pjp) throws Throwable {  
  42.         log.info("MessageQueueAopAspect2:doAround-1");  
  43.         Object obj = pjp.proceed();  
  44.         log.info("MessageQueueAopAspect2:doAround-2");  
  45.         return obj;  
  46.     }  
  47.       
  48.     @Override  
  49.     public int getOrder() {  
  50.         return 1002;  
  51.     }  
  52. }  

 

[java]  view plain  copy
 
 
 
  1. @Transactional(propagation=Propagation.REQUIRES_NEW)  
  2. @MessageQueueRequire1  
  3. @MessageQueueRequire2  
  4. public PnrPaymentErrCode bidLoan(String id){  
  5.               ...  
  6.        }  

看看執行結果:

 

 

 

 

從上面的測試我們看到,確實是order越小越是最先執行,但更重要的是最先執行的最后結束。

這個不難理解,Spring AOP就是面向切面編程,什么是切面,畫一個圖來理解下:

 

         由此得出:spring aop就是一個同心圓,要執行的方法為圓心,最外層的order最小。從最外層按照AOP1、AOP2的順序依次執行doAround方法,doBefore方法。然后執行method方法,最后按照AOP2、AOP1的順序依次執行doAfter、doAfterReturn方法。也就是說對多個AOP來說,先before的,一定后after。

        如果我們要在同一個方法事務提交后執行自己的AOP,那么把事務的AOP order設置為2,自己的AOP order設置為1,然后在doAfterReturn里邊處理自己的業務邏輯。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM