spring 增强顺序改变的原因

Spring5.2.7更改了增强顺序,原因是AspectJPrecedenceComparator在Java7及更高版本中不再有效,由于Java7后Class#getDeclaredMethods()不保证方法声明顺序,导致了advice顺序问题。修复此问题的变更影响了增强的顺序,特别是@Afteradvice的执行顺序。建议在相同@Aspect类中合并或重构advice方法以确保正确顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

spring 增强顺序改变的原因

spring 5.2.7版本正式改变增强的顺序。网上的大部分文章主要从spring的代码层面的变动,来解释增强顺序的变动,而我想要了解的是这个变动,是因为导致了某些bug的出现吗?所以自己在github和spring官网进行了查阅,寻找了其中的缘由(好吧,也是闲的)。顺便记录一下自己查找问题的思路。本文主要是根据官网的文档就行探究,没有涉及代码的分析。

spring 增强的顺序变动,在另一篇文章进行了简单的记录,里面有spring 5.2.7前后版本的切换,可以自己尝试,如果有兴趣可以自行了查阅:

https://blog.csdn.net/weixin_44457062/article/details/128710179

查找问题的步骤记录

首先,我们有 spring 5.2.7 的关键字,所以只需要在github上找到spring对应版本版本发布的记录即可,链接如下:

https://github.com/spring-projects/spring-framework/releases?expanded=true&page=6&q=v5.2.7

在这里插入图片描述

在第一个中就发现关键 advice ,然后点进 #25186 的链接跳到详情

https://github.com/spring-projects/spring-framework/issues/25186

其中比较重要的一段英文是

When the AspectJPrecedenceComparator was introduced in Spring Framework 2.0, it achieved its goal of mimicking the AspectJ compiler since the JDK at that time (i.e., Java 5) ensured that invocations of Class#geDeclaredMethods() returned an array of methods that matched the order of declaration in the source code. However, Java 7 removed this guarantee. Consequently, in Java 7 or higher, AspectJPrecedenceComparator no longer works as it is documented or as it was designed.

如有错误请纠正,大概意思如下:

AspectJPrecedenceComparator 在Spring Framework 2.0被引用,通过jdk5 的 Class#geDeclaredMethods()可以保证调用的顺序的特性进行设计,但是在jdk 7之后进行了改动,不能保证了调用的顺序,所以导致 AspectJPrecedenceComparator 不能像文档描述的那样进行执行。

最终展现出来的情况,也就是在jdk7之后,advice的顺序在某些情况下,会和正确的顺序不一样。这就是让spring修改代码的原因。

接下来的下面的英文展现了大致的可能出现的问题

PR #24673 highlights a use case where AspectJPrecedenceComparator fails to assign the highest precedence to an @After advice method (declared last in the source code). Note that an @After advice method with a precedence higher than @AfterReturning and @AfterThrowing advice methods in the same aspect will effectively be invoked last due to the try-finally implementation in AspectJAfterAdvice.invoke(MethodInvocation) which invokes proceed() in the try-block and invokeAdviceMethod() in the finally-block.

英文中的 #24673是一个超链接,记录了bug的由来,跟着时间线不断往下看,还有案例来重现bug,跳转到的链接如下:

https://github.com/spring-projects/spring-framework/pull/24673

链接里面的时间线和案例很清楚,就不记录了,自己可自行查阅。

链接里面也提到了spring的文档也做了提醒,spring官网链接:

https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#aop-ataspectj-advice-ordering

提醒部分:

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.

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.

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.

总结

由于 jdk 7 的 Class#geDeclaredMethods() 的 变化,导致在某些情况下spring的增强的顺序,不按照正常的顺序执行,所以spring进行了修复,这次修复也让 spring 的增强顺序发生了一些改变。 为什么要改变顺序才能解决这个bug,还是有点疑惑,这个可能要结合源码看具体的改动,等以后没事的时候再看看(手动🐶)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值