spring多个AOP执行先后顺序

众所周知,spring声明式事务是基于AOP实现的,那么,如果我们在同一个方法自定义多个AOP,我们如何指定他们的执行顺序呢?网上很多答案都是指定order,order越小越是最先执行,这种也不能算是错,但有些片面。

  • 配置AOP执行顺序的三种方式:

  1. 通过实现org.springframework.core.Ordered接口
    @Component
    @Aspect
    @Slf4j
    public class MessageQueueAopAspect1 implements Ordered{@Override
    	public int getOrder() {
    		// TODO Auto-generated method stub
    		return 2;
    	}
    	
    }
  2. 通过注解
    @Component
    @Aspect
    @Slf4j
    @Order(1)
    public class MessageQueueAopAspect1{
    	
    	...
    }

  3. 通过配置文件配置
    <aop:config expose-proxy="true">
    	<aop:aspect ref="aopBean" order="0">  
    		<aop:pointcut id="testPointcut"  expression="@annotation(xxx.xxx.xxx.annotation.xxx)"/>  
       		<aop:around pointcut-ref="testPointcut" method="doAround" />  
            </aop:aspect>  
    </aop:config>

我们在同一个方法上加以下两个AOP,看看究竟。

@Component
@Aspect
@Slf4j
public class MessageQueueAopAspect1 implements Ordered{
	
	@Resource(name="actionMessageProducer")
	private IProducer<MessageQueueInfo> actionProducer;	
	
	@Pointcut("@annotation(com.xxx.annotation.MessageQueueRequire1)")
	private void pointCutMethod() {
	}
	
	//声明前置通知
	@Before("pointCutMethod()")
	public void doBefore(JoinPoint point) {
		log.info("MessageQueueAopAspect1:doBefore");
		return;
	}

	//声明后置通知
	@AfterReturning(pointcut = "pointCutMethod()", returning = "returnValue")
	public void doAfterReturning(JoinPoint point,Object returnValue) {
		log.info("MessageQueueAopAspect1:doAfterReturning");
	}

	//声明例外通知
	@AfterThrowing(pointcut = "pointCutMethod()", throwing = "e")
	public void doAfterThrowing(Exception e) {
		log.info("MessageQueueAopAspect1:doAfterThrowing");
	}

	//声明最终通知
	@After("pointCutMethod()")
	public void doAfter() {
		log.info("MessageQueueAopAspect1:doAfter");
	}

	//声明环绕通知
	@Around("pointCutMethod()")
	public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
		log.info("MessageQueueAopAspect1:doAround-1");
		Object obj = pjp.proceed();
		log.info("MessageQueueAopAspect1:doAround-2");
		return obj;
	}
	
	@Override
	public int getOrder() {
		return 1001;
	}
}
@Component
@Aspect
@Slf4j
public class MessageQueueAopAspect2 implements Ordered{
	
	@Resource(name="actionMessageProducer")
	private IProducer<MessageQueueInfo> actionProducer;	
	
	@Pointcut("@annotation(com.xxx.annotation.MessageQueueRequire2)")
	private void pointCutMethod() {
	}
	
	
	//声明前置通知
	@Before("pointCutMethod()")
	public void doBefore(JoinPoint point) {
		log.info("MessageQueueAopAspect2:doBefore");
		return;
	}

	//声明后置通知
	@AfterReturning(pointcut = "pointCutMethod()", returning = "returnValue")
	public void doAfterReturning(JoinPoint point,Object returnValue) {
		log.info("MessageQueueAopAspect2:doAfterReturning");
	}

	//声明例外通知
	@AfterThrowing(pointcut = "pointCutMethod()", throwing = "e")
	public void doAfterThrowing(Exception e) {
		log.info("MessageQueueAopAspect2:doAfterThrowing");
	}

	//声明最终通知
	@After("pointCutMethod()")
	public void doAfter() {
		log.info("MessageQueueAopAspect2:doAfter");
	}

	//声明环绕通知
	@Around("pointCutMethod()")
	public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
		log.info("MessageQueueAopAspect2:doAround-1");
		Object obj = pjp.proceed();
		log.info("MessageQueueAopAspect2:doAround-2");
		return obj;
	}
	
	@Override
	public int getOrder() {
		return 1002;
	}
}

	@Transactional(propagation=Propagation.REQUIRES_NEW)
	@MessageQueueRequire1
	@MessageQueueRequire2
	public PnrPaymentErrCode bidLoan(String id){
               ...
        }

看看执行结果:


从上面的测试我们看到,确实是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里边处理自己的业务逻辑。



  • 15
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值