Spring多个AOP执行先后顺序

Spring声明式事务是基于AOP实现的,那么,如果我们在同一个方法自定义多个AOP,我们如何指定他们的执行顺序呢?
首先:配置AOP执行顺序的三种方式:

1.通过实现org.springframework.core.Ordered接口
[email protected]??
[email protected]??
[email protected]??
4.public?class?MessageQueueAopAspect1?implements?Ordered{@Override??
5.????public?int?getOrder()?{??
6.????????//?TODO?Auto-generated?method?stub??
7.return?2;
8.????}??
9.??????
10.}??

2.通过注解

[email protected]??
[email protected]??
[email protected]??
[email protected](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,看看究竟。

[email protected]??
[email protected]??
[email protected]??
4.public?class?MessageQueueAopAspect1?implements?Ordered{??
5.??????
[email protected](name="actionMessageProducer")??
7.????private?IProducer<MessageQueueInfo>?actionProducer;?????
8.??????
[email protected]("@annotation(com.xxx.annotation.MessageQueueRequire1)")??
10.????private?void?pointCutMethod()?{??
11.????}??
12.??????
13.????//声明前置通知??
[email protected]("pointCutMethod()")??
15.????public?void?doBefore(JoinPoint?point)?{??
16.????????log.info("MessageQueueAopAspect1:doBefore");??
17.????????return;??
18.????}??
19.??
20.????//声明后置通知??
[email protected](pointcut?=?"pointCutMethod()",?returning?=?"returnValue")??
22.????public?void?doAfterReturning(JoinPoint?point,Object?returnValue)?{??
23.????????log.info("MessageQueueAopAspect1:doAfterReturning");??
24.????}??
25.??
26.????//声明例外通知??
[email protected](pointcut?=?"pointCutMethod()",?throwing?=?"e")??
28.????public?void?doAfterThrowing(Exception?e)?{??
29.????????log.info("MessageQueueAopAspect1:doAfterThrowing");??
30.????}??
31.??
32.????//声明最终通知??
[email protected]("pointCutMethod()")??
34.????public?void?doAfter()?{??
35.????????log.info("MessageQueueAopAspect1:doAfter");??
36.????}??
37.??
38.????//声明环绕通知??
[email protected]("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.??????
[email protected]??
48.????public?int?getOrder()?{??
49.????????return?1001;??
50.????}??
51.}??
[email protected]??
[email protected]??
[email protected]??
4.public?class?MessageQueueAopAspect2?implements?Ordered{??
5.??????
[email protected](name="actionMessageProducer")??
7.????private?IProducer<MessageQueueInfo>?actionProducer;?????
8.??????
[email protected]("@annotation(com.xxx.annotation.MessageQueueRequire2)")??
10.????private?void?pointCutMethod()?{??
11.????}??
12.??????
13.??????
14.????//声明前置通知??
[email protected]("pointCutMethod()")??
16.????public?void?doBefore(JoinPoint?point)?{??
17.????????log.info("MessageQueueAopAspect2:doBefore");??
18.????????return;??
19.????}??
20.??
21.????//声明后置通知??
[email protected](pointcut?=?"pointCutMethod()",?returning?=?"returnValue")??
23.????public?void?doAfterReturning(JoinPoint?point,Object?returnValue)?{??
24.????????log.info("MessageQueueAopAspect2:doAfterReturning");??
25.????}??
26.??
27.????//声明例外通知??
[email protected](pointcut?=?"pointCutMethod()",?throwing?=?"e")??
29.????public?void?doAfterThrowing(Exception?e)?{??
30.????????log.info("MessageQueueAopAspect2:doAfterThrowing");??
31.????}??
32.??
33.????//声明最终通知??
[email protected]("pointCutMethod()")??
35.????public?void?doAfter()?{??
36.????????log.info("MessageQueueAopAspect2:doAfter");??
37.????}??
38.??
39.????//声明环绕通知??
[email protected]("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.??????
[email protected]??
49.????public?int?getOrder()?{??
50.????????return?1002;??
51.????}??
52.}??
[email protected](propagation=Propagation.REQUIRES_NEW)??
[email protected]??
[email protected]??
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里边处理自己的业务逻辑。

原文地址:http://blog.51cto.com/13587708/2136504

时间: 2024-08-03 23:24:02

Spring多个AOP执行先后顺序的相关文章

【转】Spring中事务与aop的先后顺序问题

[原文链接] http://my.oschina.net/HuifengWang/blog/304188 [正文] Spring中的事务是通过aop来实现的,当我们自己写aop拦截的时候,会遇到跟spring的事务aop执行的先后顺序问题,比如说动态切换数据源的问题,如果事务在前,数据源切换在后,会导致数据源切换失效,所以就用到了Order(排序)这个关键字. 步骤01:    我们可以通过在@AspectJ的方法中实现org.springframework.core.Ordered 这个接口来

AOP执行增强-Spring 源码系列(5)

AOP增强实现-Spring 源码系列(5) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Ioc容器BeanPostProcessor-Spring 源码(3) 事件机制-Spring 源码(4) AOP执行增强-Spring 源码系列(5) AOP的核心就是个动态代理,Spring进行了大量抽象和封装形成一个方便上层使用的基础模块. 而动态代理的两种实现都在上一篇中提供了代码 直接ProxyFactoryBean入手来

Spring中的AOP(五)——在Advice方法中获取目标方法的参数

摘要: 本文介绍使用Spring AOP编程中,在增强处理方法中获取目标方法的参数,定义切点表达式时使用args来快速获取目标方法的参数. 获取目标方法的信息 访问目标方法最简单的做法是定义增强处理方法时,将第一个参数定义为JoinPoint类型,当该增强处理方法被调用时,该JoinPoint参数就代表了织入增强处理的连接点.JoinPoint里包含了如下几个常用的方法: Object[] getArgs:返回目标方法的参数 Signature getSignature:返回目标方法的签名 Ob

深入分析JavaWeb Item54 -- Spring中的AOP面向切面编程2

一.在Advice方法中获取目标方法的参数 1.获取目标方法的信息 访问目标方法最简单的做法是定义增强处理方法时,将第一个参数定义为JoinPoint类型,当该增强处理方法被调用时,该JoinPoint参数就代表了织入增强处理的连接点.JoinPoint里包含了如下几个常用的方法: Object[] getArgs:返回目标方法的参数 Signature getSignature:返回目标方法的签名 Object getTarget:返回被织入增强处理的目标对象 Object getThis:返

Spring详解------------AOP

6.1.1  AOP是什么 考虑这样一个问题:需要对系统中的某些业务做日志记录,比如支付系统中的支付业务需要记录支付相关日志,对于支付系统可能相当复杂,比如可能有自己的支付系统,也可能引入第三方支付平台,面对这样的支付系统该如何解决呢? 传统解决方案: 1)日志部分提前公共类LogUtils,定义"longPayBegin"方法用于记录支付开始日志,"logPayEnd"用于记录支付结果: 2)支付部分,定义IPayService接口并定义支付方法"pay

Spring系列之AOP实现的两种方式

AOP常用的实现方式有两种,一种是采用声明的方式来实现(基于XML),一种是采用注解的方式来实现(基于AspectJ). 首先复习下AOP中一些比较重要的概念: Joinpoint(连接点):程序执行时的某个特定的点,在Spring中就是某一个方法的执行 .Pointcut(切点):说的通俗点,spring中AOP的切点就是指一些方法的集合,而这些方法是需要被增强.被代理的.一般都是按照一定的约定规则来表示的,如正则表达式等.切点是由一类连接点组成. Advice(通知):还是说的通俗点,就是在

Spring入门篇——AOP基本概念

1.什么是AOP及实现方式 什么是AOP AOP:Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术 主要的功能是:日志记录,性能统计,安全控制,事务处理,异常处理等等 AOP实现方式 预编译 -ApectJ 运行期动态代理(JDK动态代理.CGLib动态代理) -SpringAOP.JbossAOP 2.AOP基本概念 连接点:比如一个类中某个方法执行的开始 通知:在某个方法执行的时候,额外执行的切面

Spring系列之AOP的原理及手动实现

目录 Spring系列之IOC的原理及手动实现 Spring系列之DI的原理及手动实现 引入 到目前为止,我们已经完成了简易的IOC和DI的功能,虽然相比如Spring来说肯定是非常简陋的,但是毕竟我们是为了理解原理的,也没必要一定要做一个和Spring一样的东西.到了现在并不能让我们松一口气,前面的IOC和DI都还算比较简单,这里要介绍的AOP难度就稍微要大一点了. tips 本篇内容难度较大,每一步都需要理清思路,可能需要多看几遍,多画类图和手动实现更容易掌握. AOP 什么是AOP Asp

spring 注解 之 AOP基于@Aspect的AOP配置

Spring AOP面向切面编程,可以用来配置事务.做日志.权限验证.在用户请求时做一些处理等等.用@Aspect做一个切面,就可以直接实现. 1.首先定义一个切面类,加上@Component  @Aspect这两个注解 @Component@Aspectpublic class LogAspect { private static final Logger logger = LoggerFactory.getLogger(LogAspect.class); private static fin