Spring多個AOP執行先後順序
阿新 • • 發佈:2018-07-05
color 設置 resource ges cto 圖片 邏輯 依次 errcode Spring聲明式事務是基於AOP實現的,那麽,如果我們在同一個方法自定義多個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執行先後順序