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执行先后顺序
         由此得出:spring aop就是一个同心圆,要执行的方法为圆心,最外层的order最小。从最外层按照AOP1、AOP2的顺序依次执行doAround方法,doBefore方法。然后执行method方法,最后按照AOP2、AOP1的顺序依次执行doAfter、doAfterReturn方法。也就是说对多个AOP来说,先before的,一定后after。
        如果我们要在同一个方法事务提交后执行自己的AOP,那么把事务的AOP order设置为2,自己的AOP order设置为1,然后在doAfterReturn里边处理自己的业务逻辑。

转载于:https://blog.51cto.com/13587708/2136504

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值