Spring AOP 通知执行顺序

  • 1)当多个切面的通知切入到同一个切入点时,他们的执行顺序是什么样的?可以调整顺序吗?

  • 2)当一个切面的多个不同类型通知切入到同一切入点时,他的执行顺序是什么样的?

  • 3)当一个切面的多个相同类型通知切入到同一切入点时,他的执行顺序是什么样的?

首先:

Spring官网文档中关于 AOP的执行顺序描述已经很详细【Version 5.3.6】:Core Technologies

来,练练英语:

Advice Ordering

What happens when multiple pieces of advice all want to run at the same join point? Spring AOP follows the same precedence rules as AspectJ to determine the order of advice execution. The highest precedence advice runs first "on the way in" (so, given two pieces of before advice, the one with highest precedence runs first). "On the way out" from a join point, the highest precedence advice runs last (so, given two pieces of after advice, the one with the highest precedence will run second).

天书的第一段告诉我们什么?

  • Spring AOP遵循着和AspectJ相同的通知方法执行顺序。在进入切入点时,最高优先级的通知方法总是最先执行;在离开切入点时,最高优先级的通知方法总是最后执行。

例如两个 after 通知,高优先级的 after 通知会第二个执行。

此时就可以拿出 popular 的网图了:根据执行顺序的特点,不同优先级的通知方法的执行顺序就像一个包裹的同心圆,高优先级的通知方法总是包裹在外面的那个。

2020122144408211.png

 

When two pieces of advice defined in different aspects both need to run at the same join point, unless you specify otherwise, the order of execution is undefined. You can control the order of execution by specifying precedence. This is done in the normal Spring way by either implementing the org.springframework.core.Ordered interface in the aspect class or annotating it with the @Order annotation. Given two aspects, the aspect returning the lower value from Ordered.getOrder() (or the annotation value) has the higher precedence.

天书的第二段说了啥?

  • 当两个通知方法定义在不同切面,但却是同一切入点中。此时是无法确定执行顺序的,除非你指定通知方法的执行优先级【order】,order值越小,优先级越高。

看到这里,是不是解答了我们的第一个问题了?

那么我们该怎么指定执行顺序呢?有如下几种办法:

  • 方法1:让切面方法实现 org.springframework.core.Ordered 接口,返回其切面的优先级

  • 方法2:通过对切面加Order 注解,指定优先级

  • 方法3:通过xml配置文件,指定aop:aspect的优先级

下面来介绍具体执行过程:

  • 让切面方法实现 org.springframework.core.Ordered 接口:

@Component 
@Aspect 
@Slf4j 
public class MessageQueueAopAspect1 implements Ordered{
  @Override 
  public int getOrder() { return 2; } 
} 
  • 通过注解

@Component 
@Aspect 
@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> 

Each of the distinct advice types of a particular aspect is conceptually meant to apply to the join point directly. As a consequence, an @AfterThrowing advice method is not supposed to receive an exception from an accompanying @After/@AfterReturning method.

看习惯后,天书也逐渐变得人能看了:

  • 同一切面中的不同的通知方法,都是直接运作在切入点的。所以,形如 @AfterThrowing这种类型的通知方法,不应该捕获@After/@AfterReturning 抛出的异常。

As of Spring Framework 5.2.7, advice methods defined in the same @Aspect class that need to run at the same join point are assigned precedence based on their advice type in the following order, from highest to lowest precedence: @Around, @Before, @After, @AfterReturning, @AfterThrowing. Note, however, that an @After advice method will effectively be invoked after any @AfterReturning or @AfterThrowing advice methods in the same aspect, following AspectJ’s "after finally advice" semantics for @After.

  • Spring Framework 5.2.7 以后,同一切面中,对同一切入点的不同的通知方法,是存在执行优先级的。具体优先级从高到低为:@Around, @Before, @After, @AfterReturning, @AfterThrowing

看到这,我们的问题2)是不是也解决了?

When two pieces of the same type of advice (for example, two @After advice methods) defined in the same @Aspect class both need to run at the same join point, the ordering is undefined (since there is no way to retrieve the source code declaration order through reflection for javac-compiled classes). Consider collapsing such advice methods into one advice method per join point in each @Aspect class or refactor the pieces of advice into separate @Aspect classes that you can order at the aspect level via Ordered or @Order.

终于来到了最后一段:

  • 同一切面中,对同一切入点,有多个相同的通知方法。这种情况下,执行顺序是不明确的。

  • 可以考虑将这两个相同的通知方法合并成一个通知方法,或者将两个通知方法拆分到两个切面类中去,然后用 Order

来指定两者的执行顺序。

这样第三个问题也解决啦!

参考文档

https://www.jb51.net/article/179078.htm

Spring AOP 通知执行顺序《一》同一切面不同类型通知_灵颖桥人的博客-CSDN博客

Core Technologies

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值