Go to file
Sam Brannen 0998bd49ef Implement reliable advice invocation order within an @Aspect
The AspectJPrecedenceComparator was designed to mimic the precedence
order enforced by the AspectJ compiler with regard to multiple 'after'
methods defined within the same aspect whose pointcuts match the same
joinpoint. Specifically, if an aspect declares multiple @After,
@AfterReturning, or @AfterThrowing advice methods whose pointcuts match
the same joinpoint, such 'after' advice methods should be invoked in
the reverse order in which they are declared in the source code.

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 an invocation 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 when sorting advice methods in a single @Aspect class.
Note, however, that AspectJPrecedenceComparator continues to work as
documented and designed when sorting advice configured via the
<aop:aspect> XML namespace element.

PR gh-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() which invokes
proceed() in the try-block and invokeAdviceMethod() in the
finally-block.

Since Spring cannot reliably determine the source code declaration
order of annotated advice methods without using ASM to analyze the byte
code, this commit introduces reliable invocation order for advice
methods declared within a single @Aspect. Specifically, the
getAdvisors(...) method in ReflectiveAspectJAdvisorFactory now hard
codes the declarationOrderInAspect to `0` instead of using the index of
the current advice method. This is necessary since the index no longer
has any correlation to the method declaration order in the source code.
The result is that all advice methods discovered via reflection will
now be sorted only according to the precedence rules defined in the
ReflectiveAspectJAdvisorFactory.METHOD_COMPARATOR. Specifically, advice
methods within a single @Aspect will be sorted in the following order
(with @After advice methods effectively invoked after @AfterReturning
and @AfterThrowing advice methods): @Around, @Before, @After,
@AfterReturning, @AfterThrowing.

The modified assertions in AspectJAutoProxyAdviceOrderIntegrationTests
demonstrate the concrete effects of this change.

Closes gh-25186
2020-06-08 14:18:28 +02:00
.github Configure Gradle wrapper validation action 2020-06-02 14:43:45 +02:00
buildSrc Fix typo in buildSrc/README.md 2020-03-14 10:06:25 +01:00
framework-bom Remove scope information from published BOM 2019-09-18 15:27:59 +02:00
gradle Upgrade to spring-doc-resources 0.2.1 2020-04-14 13:36:11 +02:00
integration-tests Implement reliable advice invocation order within an @Aspect 2020-06-08 14:18:28 +02:00
spring-aop Implement reliable advice invocation order within an @Aspect 2020-06-08 14:18:28 +02:00
spring-aspects Remove unnecessary dependency on spring-orm 2020-02-17 20:54:58 +01:00
spring-beans Polishing 2020-05-29 15:52:39 +02:00
spring-context Support for shared GroovyClassLoader in GroovyScriptFactory 2020-06-06 13:21:20 +02:00
spring-context-indexer Polish contribution 2020-03-26 16:52:24 +01:00
spring-context-support Polishing 2020-05-22 16:23:46 +02:00
spring-core Polishing 2020-05-29 15:52:39 +02:00
spring-expression Use autoboxing instead of explicit wrapping in tests 2020-04-01 14:34:20 +02:00
spring-instrument Delete obsolete log4j config 2020-03-18 17:01:01 +01:00
spring-jcl Polishing 2020-01-28 21:56:35 +01:00
spring-jdbc Clarify JDBC-defined negative values returned from batchUpdate 2020-05-29 15:51:19 +02:00
spring-jms Use autoboxing instead of explicit wrapping in tests 2020-04-01 14:34:20 +02:00
spring-messaging Consistent not-null assertions for configured interceptors 2020-05-18 14:23:05 +02:00
spring-orm Consistently refer to FlushMode.MANUAL instead of outdated NEVER 2020-05-29 15:51:54 +02:00
spring-oxm Use SingletonSupplier for XStream instance in XStreamMarshaller 2020-05-07 12:35:32 +02:00
spring-test Polishing 2020-06-06 17:45:12 +02:00
spring-tx Consistently refer to FlushMode.MANUAL instead of outdated NEVER 2020-05-29 15:51:54 +02:00
spring-web Polishing 2020-06-06 18:49:32 +02:00
spring-webflux Polishing 2020-06-06 18:49:32 +02:00
spring-webmvc Pre-calculated RequestMappingInfo hashcode 2020-06-03 06:11:35 +01:00
spring-websocket Extend readOnlyWebSocketHttpHeaders deprecation to 5.1.16 2020-06-06 14:41:06 +02:00
src Support for shared GroovyClassLoader in GroovyScriptFactory 2020-06-06 13:21:20 +02:00
.editorconfig Add EditorConfig 2017-06-12 08:07:54 +02:00
.gitattributes Ensure line endings for binary files are not modified in Git 2019-10-18 11:56:18 +02:00
.gitignore Rename non-Framework project modules 2019-08-21 14:32:25 +02:00
.mailmap Change gopivotal.com to pivotal.io 2014-10-05 18:12:50 +02:00
CODE_OF_CONDUCT.adoc URL Cleanup 2019-03-21 15:08:55 -05:00
CONTRIBUTING.md Update StackOverflow link 2020-04-20 12:32:11 +01:00
LICENSE.txt Add LICENSE.txt file 2019-08-20 22:01:12 +02:00
README.md Fix grammar 2019-11-05 15:20:18 +01:00
SECURITY.md Create SECURITY.md 2019-05-23 11:36:52 -04:00
build.gradle Upgrade to Jetty Reactive HttpClient 1.1.3 2020-06-06 18:49:47 +02:00
gradle.properties Next Development Version 2020-04-28 10:58:49 +02:00
gradlew Upgrade to Gradle 5.6 2019-08-17 19:20:36 +02:00
gradlew.bat Revert "Upgrade to Gradle 5.6.3" 2019-10-18 10:38:40 +02:00
import-into-eclipse.md Polishing regarding AJDT versions 2020-01-13 17:15:27 +01:00
import-into-idea.md URL Cleanup 2019-03-21 15:08:55 -05:00
settings.gradle Unpublish Gradle metadata 2019-12-02 16:43:02 +01:00

README.md

Spring Framework Build Status

This is the home of the Spring Framework: the foundation for all Spring projects. Collectively the Spring Framework and the family of Spring projects are often referred to simply as "Spring".

Spring provides everything required beyond the Java programming language for creating enterprise applications for a wide range of scenarios and architectures. Please read the Overview section as reference for a more complete introduction.

Code of Conduct

This project is governed by the Spring Code of Conduct. By participating, you are expected to uphold this code of conduct. Please report unacceptable behavior to spring-code-of-conduct@pivotal.io.

Access to Binaries

For access to artifacts or a distribution zip, see the Spring Framework Artifacts wiki page.

Documentation

The Spring Framework maintains reference documentation (published and source), Github wiki pages, and an API reference. There are also guides and tutorials across Spring projects.

Build from Source

See the Build from Source Wiki page and the CONTRIBUTING.md file.

Stay in Touch

Follow @SpringCentral, @SpringFramework, and its team members on Twitter. In-depth articles can be found at The Spring Blog, and releases are announced via our news feed.

License

The Spring Framework is released under version 2.0 of the Apache License.