Spring AOP执行先后顺序实例详解

所属分类: 软件编程 / java 阅读数: 41
收藏 0 赞 0 分享

这篇文章主要介绍了Spring AOP执行先后顺序实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

众所周知,spring声明式事务是基于AOP实现的,那么,如果我们在同一个方法自定义多个AOP,我们如何指定他们的执行顺序呢?

网上很多答案都是指定order,order越小越是最先执行,这种也不能算是错,但有些片面。

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

通过实现org.springframework.core.Ordered接口

@Component 
@Aspect 
@Slf4j 
public class MessageQueueAopAspect1 implements Ordered{@Override 
  public int getOrder() { 
    // TODO Auto-generated method stub 
    return 2; 
  } 
   
} 

通过注解

@Component 
@Aspect 
@Slf4j 
@Order(1) 
public class MessageQueueAopAspect1{ 
   
  ... 
} 

通过配置文件配置

<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里边处理自己的业务逻辑。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

更多精彩内容其他人还在看

java 中maven pom.xml文件教程详解

这篇文章主要介绍了java 中maven pom.xml文件教程详解,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

spring boot整合netty的实现方法

这篇文章主要介绍了spring boot整合netty的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

Netty与Spring Boot的整合实现

这篇文章主要介绍了Netty与Spring Boot的整合的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

Spring动态加载bean后调用实现方法解析

这篇文章主要介绍了Spring动态加载bean后调用实现方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
收藏 0 赞 0 分享

java实现画图板上画一条直线

这篇文章主要为大家详细介绍了java实现画图板上画一条直线,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

Java通过python命令执行DataX任务的实例

今天小编就为大家分享一篇Java通过python命令执行DataX任务的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
收藏 0 赞 0 分享

springBoot集成redis的key,value序列化的相关问题

这篇文章主要介绍了springBoot集成redis的key,value序列化的相关问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

java实现登录案例

这篇文章主要为大家详细介绍了java实现登录案例的相关代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

java解决请求跨域的两种方法

这篇文章主要为大家详细介绍了java解决请求跨域的两种方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

SpringBoot集成Beetl后统一处理页面异常的方法

这篇文章主要介绍了SpringBoot集成Beetl后统一处理页面异常的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享
查看更多