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) {