A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 我是色色 于 2017-9-25 11:10 编辑

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

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马