Based on the findings in #24961 and #24970, it appears that we can improve the runtime performance for method parameter annotations synthesized due to their use of @AliasFor
.
Annotations such as @RequestParam
can only be declared directly on parameters (due to the @Target(ElementType.PARAMETER)
declaration). Consequently, they can never be merged in the sense of findMergedAnnotation()
. Similarly, the internal data structures in the MergedAnnotation
API that support annotation attribute overriding (i.e., "merging") are never used for such annotations.
In addition, within the Spring Framework, @RequestParam
is only looked up via SynthesizingMethodParameter
, which delegates to AnnotationUtils.synthesizeAnnotation()
to support the use of @AliasFor
.
In 5.2.x, this is implemented using MergedAnnotation.from(...)
:
https://github.com/spring-projects/spring-framework/blob/73fadd8b7c02938a0155ff49a40b4257092d1dc4/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java#L1188-L1195
Whereas, in 5.1.x, this is implemented using the DefaultAnnotationAttributeExtractor
:
https://github.com/spring-projects/spring-framework/blob/ea7b0103c5b9ab403b75197f5f1f4582c85eb2fd/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java#L1556-L1574
The major difference here is that direct use of DefaultAnnotationAttributeExtractor
avoids any extra overhead incurred by searching for annotation attribute overrides. In addition, DefaultAnnotationAttributeExtractor
uses a direct approach for accessing the non-aliased values of the original annotation, thereby avoiding any complex lookups, conversions, adaptations, etc.
For example, if we still had a direct lookup mechanism for the required
attribute in @RequestParam
, then #24961 never would have surfaced as a regression since TypeMappedAnnotation.getValue(...)
would not come into play.
In summary, the use of the MergedAnnotation
API for direct synthesis of a single annotation without any form of attribute override support results in unnecessary runtime overhead and a regression in performance in Spring Framework 5.2.x.
We should therefore consider reintroducing the DefaultAnnotationAttributeExtractor
/ MapAnnotationAttributeExtractor
dichotomy that existed prior to 5.2, or we should investigate an alternative means for synthesizing an annotation directly from a concrete annotation instance with limited support for @AliasFor
for locally aliased attributes as is needed by clients such as SynthesizingMethodParameter
.
Comment From: sbrannen
Closing this issue since there have been no reports from the community regarding regressions in performance.
We may revisit this at a later date if we receive reports of performance regressions.