Spring聲明式事務是基於AOP實現的,那麼,若是咱們在同一個方法自定義多個AOP,咱們如何指定他們的執行順序呢?spring
首先:配置AOP執行順序的三種方式:express
1. 經過實現org.springframework.core.Ordered接口編程
1. @Component ide
2. @Aspect 測試
3. @Slf4j ui
4. public class MessageQueueAopAspect1 implements Ordered{@Override 接口
5. public int getOrder() { 事務
6. // TODO Auto-generated method stub get
7. return 2;it
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最小。從最外層按照AOP一、AOP2的順序依次執行doAround方法,doBefore方法。而後執行method方法,最後按照AOP二、AOP1的順序依次執行doAfter、doAfterReturn方法。也就是說對多個AOP來講,先before的,必定後after。
若是咱們要在同一個方法事務提交後執行本身的AOP,那麼把事務的AOP order設置爲2,本身的AOP order設置爲1,而後在doAfterReturn裏邊處理本身的業務邏輯。