【传智播客郑州校区分享】Spring多个AOP执行先后顺序

来源:互联网 发布:sql优化面试题 编辑:程序博客网 时间:2024/04/28 22:32

【传智播客郑州校区分享】Spring多个AOP执行先后顺序

 文/传智播客郑州校区就业部

Spring声明式事务是基于AOP实现的,那么,如果我们在同一个方法自定义多个AOP,我们如何指定他们的执行顺序呢?

首先:配置AOP执行顺序的三种方式:

1. 通过实现org.springframework.core.Ordered接口

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. 通过注解

1. @Component  

2. @Aspect  

3. @Slf4j  

4. @Order(1)  

5. public class MessageQueueAopAspect1{  

6.       

7.     ...  

8. }  

 

3. 通过配置文件配置

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,看看究竟。

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. }  

 

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. }  

 

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里边处理自己的业务逻辑。

阅读全文
1 0
原创粉丝点击