zoukankan      html  css  js  c++  java
  • spring多个AOP执行先后顺序(面试问题:怎么控制多个aop的执行循序)

    转载:spring多个AOP执行先后顺序(面试问题:怎么控制多个aop的执行循序)

    众所周知,spring声明式事务是基于AOP实现的,那么,如果我们在同一个方法自定义多个AOP,我们如何指定他们的执行顺序呢?网上很多答案都是指定order,order越小越是最先执行,这种也不能算是错,但有些片面。

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

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

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

    通过注解

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

    通过配置文件配置

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

  • 相关阅读:
    A2-02-15.DML-MySQL RIGHT JOIN
    A2-02-14.DML- MySQL LEFT JOIN
    A2-02-13.DML- MySQL INNER JOIN
    NHibernate N+1问题实例分析和优化
    怎么创建移动页面应用程序
    .NET开发时让人头痛的SESSION超时
    WCF服务编程——数据契约快速入门
    数据模型类对比,用反射做个快乐的程序员
    javascript常见数据集
    provider:命名管道提供程序,error:40
  • 原文地址:https://www.cnblogs.com/fanguangdexiaoyuer/p/10562069.html
Copyright © 2011-2022 走看看