1. 程式人生 > >Spring多個AOP執行先後順序

Spring多個AOP執行先後順序

color 設置 resource ges cto 圖片 邏輯 依次 errcode

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裏邊處理自己的業務邏輯。

Spring多個AOP執行先後順序