为了账号安全,请及时绑定邮箱和手机立即绑定

Spring多个AOP执行先后顺序

标签:
Java

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

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消