Overview

This PR has two commits: one that stops using SynthesizedAnnotation and a second that deprecates SynthesizedAnnotation.

If we decide to get rid of SynthesizedAnnotation, we can subsequently remove it completely for Spring Framework 6.0.

Discussion

SynthesizedAnnotation was originally introduced as a convenience for easily detecting if an annotation had been synthesized by Spring via a simple if (myAnnotation instanceof SynthesizedAnnotation) check.

However, the introduction of SynthesizedAnnotation in the JDK proxy for an annotation results in a separate proxy class for Spring's synthesized annotations, and this causes issues with GraalVM native images since users and framework developers must always ensure that the additional proxy classes are registered.

This PR completely removes the use of SynthesizedAnnotation in synthesized proxies which allows the JDK proxy class for the annotation to be reused within a GraalVM native image. See this project for a demonstration.

Instead of checking if an annotation implements SynthesizedAnnotation (to determine if the annotation needs to be synthesized), the PR uses a Proxy.getInvocationHandler(annotation) instanceof SynthesizedMergedAnnotationInvocationHandler) check to determine if Spring synthesized the annotation.

Drawbacks

At one point in 2015, @jhoeller used Proxy.getInvocationHandler to perform the "is synthesized" check; however, he reverted that due to #18402. See https://github.com/spring-projects/spring-framework/issues/18402#issuecomment-453434657 for details.

Related Issues

  • 18271

  • 18402

  • 29053

  • 29054

Deliverables

  • [x] Determine if we can make Proxy.getInvocationHandler work without negative side effects such as those raised in #18402