spring多个AOP执行先后顺序

程序员考拉

共 4241字,需浏览 9分钟

 ·

2020-08-07 13:39


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


网上很多答案都是指定order,order越小越是最先执行,这种也不能算是错,但有些片面。


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

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


    @Component  
        @Aspect  
        @Slf4j  
        public class MessageQueueAopAspect1 implements Ordered{@Override  
            public int getOrder() {
                // TODO Auto-generated method stub
                return 2;
            }
              
        }


  2. 通过注解


    @Component  
        @Aspect  
        @Slf4j  
        @Order(1)
        public class MessageQueueAopAspect1{
              
            ...
        }


  3. 通过配置文件配置


    <aop:config expose-proxy="true">  
            <aop:aspect ref="aopBean" order="0">    
                <aop:pointcut id="testPointcut"  expression="@annotation(xxx.xxx.xxx.annotation.xxx)"/>    
                <aop:around pointcut-ref="testPointcut" method="doAround" />    
                aop:aspect>    
        aop:config>


我们在同一个方法上加以下两个AOP,看看究竟。


@Component  
    @Aspect  
    @Slf4j
    public class MessageQueueAopAspect1 implements Ordered{
          
        @Resource(name="actionMessageProducer")
        private IProducer actionProducer;
          
        @Pointcut("@annotation(com.xxx.annotation.MessageQueueRequire1)")
        private void pointCutMethod() {
        }
          
        //声明前置通知
        @Before("pointCutMethod()")
        public void doBefore(JoinPoint point) {
            log.info("MessageQueueAopAspect1:doBefore");
            return;
        }
      
        //声明后置通知
        @AfterReturning(pointcut = "pointCutMethod()", returning = "returnValue")
        public void doAfterReturning(JoinPoint point,Object returnValue) {
            log.info("MessageQueueAopAspect1:doAfterReturning");
        }
      
        //声明例外通知
        @AfterThrowing(pointcut = "pointCutMethod()", throwing = "e")
        public void doAfterThrowing(Exception e) {
            log.info("MessageQueueAopAspect1:doAfterThrowing");
        }
      
        //声明最终通知
        @After("pointCutMethod()")
        public void doAfter() {
            log.info("MessageQueueAopAspect1:doAfter");
        }
      
        //声明环绕通知
        @Around("pointCutMethod()")
        public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
            log.info("MessageQueueAopAspect1:doAround-1");
            Object obj = pjp.proceed();
            log.info("MessageQueueAopAspect1:doAround-2");
            return obj;
        }
          
        @Override  
        public int getOrder() {
            return 1001;
        }
    }


@Component  
@Aspect  
@Slf4j
public class MessageQueueAopAspect2 implements Ordered{
      
    @Resource(name="actionMessageProducer")
    private IProducer actionProducer;
      
    @Pointcut("@annotation(com.xxx.annotation.MessageQueueRequire2)")
    private void pointCutMethod() {
    }
      
      
    //声明前置通知
    @Before("pointCutMethod()")
    public void doBefore(JoinPoint point) {
        log.info("MessageQueueAopAspect2:doBefore");
        return;
    }
  
    //声明后置通知
    @AfterReturning(pointcut = "pointCutMethod()", returning = "returnValue")
    public void doAfterReturning(JoinPoint point,Object returnValue) {
        log.info("MessageQueueAopAspect2:doAfterReturning");
    }
  
    //声明例外通知
    @AfterThrowing(pointcut = "pointCutMethod()", throwing = "e")
    public void doAfterThrowing(Exception e) {
        log.info("MessageQueueAopAspect2:doAfterThrowing");
    }
  
    //声明最终通知
    @After("pointCutMethod()")
    public void doAfter() {
        log.info("MessageQueueAopAspect2:doAfter");
    }
  
    //声明环绕通知
    @Around("pointCutMethod()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        log.info("MessageQueueAopAspect2:doAround-1");
        Object obj = pjp.proceed();
        log.info("MessageQueueAopAspect2:doAround-2");
        return obj;
    }
      
    @Override  
    public int getOrder() {
        return 1002;
    }
}


@Transactional(propagation=Propagation.REQUIRES_NEW)
    @MessageQueueRequire1  
    @MessageQueueRequire2  
    public PnrPaymentErrCode bidLoan(String id){
                  ...
           }


看看执行结果:



从上面的测试我们看到,确实是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里边处理自己的业务逻辑。


出处:cnblogs.com/panchanggui/p/12203066.html




点个“在看”哦!

浏览 33
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报