Spring AOP的执行顺序
众所周知,spring声明式事务是基于AOP实现的,那么,如果我们在同一个方法自定义多个AOP,我们如何指定他们的执行顺序呢?
配置AOP执行顺序的三种方式
通过实现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 }
通过注解
1 @Component 2 @Aspect 3 @Slf4j 4 @Order(1) 5 public class MessageQueueAopAspect1{ 6 7 ... 8 }
通过配置文件配置
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 }
测试结果
从上面的测试我们看到,确实是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里边处理自己的业务逻辑。
转载:https://www.cnblogs.com/fanguangdexiaoyuer/p/10562069.html