Synthesized annotations that contain arrays and/or strings do not generate the same toString()
value as the non-synthesized version.
The non-synthesized annotation's toString()
method returns a string which is a code equivalent version of that annotation meaning that you can take the result of the toString()
, copy and paste it into code, and have it compile. This is very convenient when writing a code generation library since it allows you to copy annotations.
This does not work with synthesized annotations though as the way the array gets serialized in toString()
doesn't match.
Actual Annotation:
@Bean("testValue")
Non-Synthesized Annotation toString()
:
@org.springframework.context.annotation.Bean(value = {"testValue"})
Synthesized Annotation toString()
:
@org.springframework.context.annotation.Bean(value = [testValue])
https://github.com/spring-projects/spring-framework/blob/a0c97e4c36e5e07bc13bab4409ec740332a57871/spring-core/src/main/java/org/springframework/core/annotation/SynthesizedMergedAnnotationInvocationHandler.java#L202
Comment From: sbrannen
This is actually by design.
The result of invoking toString()
on a synthesized annotation is identical to the result of invoking toString()
on the same non-synthesized annotation on Java 8. In fact we used to have tests in place to verify that, but those broke once we started building the framework on Java 9, since Java 9 changed the output format for toString()
in annotations.
See:
-
19211
- commit faf6e5d8fa05d25504a2f8dcd1ced4931aa82f11
In any case, it does not appear that the JDK format has changed since Java 9, so I'll go ahead and update to the newer format.
Comment From: jhoeller
Ah ok, I wasn't aware of the change between JDK 8 and 9 there. If 5.3.x is currently aligned with the JDK 8 toString format there, we could also simply upgrade to the JDK 9+ format for 6.0.
Comment From: sbrannen
Interestingly enough, it turns out there are actually 2 bugs (🐛) lurking behind the scenes here.
- Spring's
toString()
for synthesized annotations in fact did not match the JDK 8 behavior for class attributes. Spring usedClass#getName
; JDK 8 usedClass#toString
. - JDK 9+ incorrectly invokes
Enum#toString
for enum attributes; whereas, the commit I am about to push will useEnum#name
, since an enum can in fact overridetoString()
(for example, withreturn name().toLowerCase()
).
I'll see if the OpenJDK team is willing to update the toString()
implementation for annotations to use Enum#name
.
Comment From: sbrannen
I'll see if the OpenJDK team is willing to update the
toString()
implementation for annotations to useEnum#name
.
See: https://bugs.openjdk.java.net/browse/JDK-8281462
Comment From: sbrannen
Reopening to address additional shortcomings in the toString()
implementation for synthesized annotations.