diff --git a/spring-core/src/main/java/org/springframework/core/annotation/SynthesizedMergedAnnotationInvocationHandler.java b/spring-core/src/main/java/org/springframework/core/annotation/SynthesizedMergedAnnotationInvocationHandler.java
index 1a98466a6d..16a5e82b4b 100644
--- a/spring-core/src/main/java/org/springframework/core/annotation/SynthesizedMergedAnnotationInvocationHandler.java
+++ b/spring-core/src/main/java/org/springframework/core/annotation/SynthesizedMergedAnnotationInvocationHandler.java
@@ -58,6 +58,9 @@ final class SynthesizedMergedAnnotationInvocationHandler i
@Nullable
private volatile Integer hashCode;
+ @Nullable
+ private volatile String string;
+
private SynthesizedMergedAnnotationInvocationHandler(MergedAnnotation annotation, Class type) {
Assert.notNull(annotation, "MergedAnnotation must not be null");
@@ -78,7 +81,7 @@ final class SynthesizedMergedAnnotationInvocationHandler i
return annotationHashCode();
}
if (ReflectionUtils.isToStringMethod(method)) {
- return this.annotation.toString();
+ return annotationToString();
}
if (isAnnotationTypeMethod(method)) {
return this.type;
@@ -171,6 +174,44 @@ final class SynthesizedMergedAnnotationInvocationHandler i
return value.hashCode();
}
+ private String annotationToString() {
+ String string = this.string;
+ if (string == null) {
+ StringBuilder builder = new StringBuilder("@").append(this.type.getName()).append("(");
+ for (int i = 0; i < this.attributes.size(); i++) {
+ Method attribute = this.attributes.get(i);
+ if (i > 0) {
+ builder.append(", ");
+ }
+ builder.append(attribute.getName());
+ builder.append("=");
+ builder.append(toString(getAttributeValue(attribute)));
+ }
+ builder.append(")");
+ string = builder.toString();
+ this.string = string;
+ }
+ return string;
+ }
+
+ private String toString(Object value) {
+ if (value instanceof Class) {
+ return ((Class>) value).getName();
+ }
+ if (value.getClass().isArray()) {
+ StringBuilder builder = new StringBuilder("[");
+ for (int i = 0; i < Array.getLength(value); i++) {
+ if (i > 0) {
+ builder.append(", ");
+ }
+ builder.append(toString(Array.get(value, i)));
+ }
+ builder.append("]");
+ return builder.toString();
+ }
+ return String.valueOf(value);
+ }
+
private Object getAttributeValue(Method method) {
Object value = this.valueCache.computeIfAbsent(method.getName(), attributeName -> {
Class> type = ClassUtils.resolvePrimitiveIfNecessary(method.getReturnType());
@@ -188,7 +229,7 @@ final class SynthesizedMergedAnnotationInvocationHandler i
}
/**
- * Clone the provided array, ensuring that original component type is retained.
+ * Clone the provided array, ensuring that the original component type is retained.
* @param array the array to clone
*/
private Object cloneArray(Object array) {
diff --git a/spring-core/src/main/java/org/springframework/core/annotation/TypeMappedAnnotation.java b/spring-core/src/main/java/org/springframework/core/annotation/TypeMappedAnnotation.java
index 0ff07a0992..ede74c09ba 100644
--- a/spring-core/src/main/java/org/springframework/core/annotation/TypeMappedAnnotation.java
+++ b/spring-core/src/main/java/org/springframework/core/annotation/TypeMappedAnnotation.java
@@ -110,9 +110,6 @@ final class TypeMappedAnnotation extends AbstractMergedAnn
private final int[] resolvedMirrors;
- @Nullable
- private String string;
-
private TypeMappedAnnotation(AnnotationTypeMapping mapping, @Nullable ClassLoader classLoader,
@Nullable Object source, @Nullable Object rootAttributes, ValueExtractor valueExtractor,
@@ -346,48 +343,6 @@ final class TypeMappedAnnotation extends AbstractMergedAnn
return this.mapping.isSynthesizable();
}
- @Override
- public String toString() {
- String string = this.string;
- if (string == null) {
- StringBuilder builder = new StringBuilder();
- builder.append("@");
- builder.append(getType().getName());
- builder.append("(");
- for (int i = 0; i < this.mapping.getAttributes().size(); i++) {
- Method attribute = this.mapping.getAttributes().get(i);
- builder.append(i == 0 ? "" : ", ");
- builder.append(attribute.getName());
- builder.append("=");
- builder.append(toString(getValue(i, Object.class)));
- }
- builder.append(")");
- string = builder.toString();
- this.string = string;
- }
- return string;
- }
-
- private Object toString(@Nullable Object value) {
- if (value == null) {
- return "";
- }
- if (value instanceof Class) {
- return ((Class>) value).getName();
- }
- if (value.getClass().isArray()) {
- StringBuilder builder = new StringBuilder();
- builder.append("[");
- for (int i = 0; i < Array.getLength(value); i++) {
- builder.append(i == 0 ? "" : ", ");
- builder.append(toString(Array.get(value, i)));
- }
- builder.append("]");
- return builder.toString();
- }
- return String.valueOf(value);
- }
-
@Override
@Nullable
protected T getAttributeValue(String attributeName, Class type) {