aop 执行顺序

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

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

 

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

    [java] view plain copy

    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. 通过注解

    [java] view plain copy

    1. @Component

    2. @Aspect

    3. @Slf4j

    4. @Order(1)

    5. public class MessageQueueAopAspect1{

    6.  

    7. ...

    8. }

  3. 通过配置文件配置

    [html] view plain copy

    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,看看究竟。

 

[java] view plain copy

  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. }

[java] view plain copy

  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. }

 

[java] view plain copy

  1. @Transactional(propagation=Propagation.REQUIRES_NEW)

  2. @MessageQueueRequire1

  3. @MessageQueueRequire2

  4. public PnrPaymentErrCode bidLoan(String id){

  5. ...

  6. }

看看执行结果:

aop 执行顺序

从上面的测试我们看到,确实是order越小越是最先执行,但更重要的是最先执行的最后结束。

这个不难理解,spring AOP就是面向切面编程,什么是切面,画一个图来理解下:

aop 执行顺序

由此得出:spring aop就是一个同心圆,要执行的方法为圆心,最外层的order最小。从最外层按照AOP1、AOP2的顺序依次执行doAround方法,doBefore方法。然后执行method方法,最后按照AOP2、AOP1的顺序依次执行doAfter、doAfterReturn方法。也就是说对多个AOP来说,先before的,一定后after。

如果我们要在同一个方法事务提交后执行自己的AOP,那么把事务的AOP order设置为2,自己的AOP order设置为1,然后在doAfterReturn里边处理自己的业务逻辑。

上一篇:java自定义注解以及结合AOP的使用


下一篇:【Spring】代理模式--动态代理