From 53430760f34f7326213637710a39f1924dd52797 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 9 Oct 2018 23:14:13 +0200 Subject: [PATCH] Consistent exposure of empty attribute arrays in AnnotationMetadata Issue: SPR-17347 (cherry picked from commit 83909e6e1e1c70090ebdbb791bf9a8a21e901430) --- .../RecursiveAnnotationArrayVisitor.java | 17 +++++++++++++++++ .../core/type/AnnotationMetadataTests.java | 8 ++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/core/type/classreading/RecursiveAnnotationArrayVisitor.java b/spring-core/src/main/java/org/springframework/core/type/classreading/RecursiveAnnotationArrayVisitor.java index af97f44ecf..a4530bb79b 100644 --- a/spring-core/src/main/java/org/springframework/core/type/classreading/RecursiveAnnotationArrayVisitor.java +++ b/spring-core/src/main/java/org/springframework/core/type/classreading/RecursiveAnnotationArrayVisitor.java @@ -16,6 +16,7 @@ package org.springframework.core.type.classreading; +import java.lang.annotation.Annotation; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.List; @@ -27,6 +28,8 @@ import org.springframework.lang.Nullable; import org.springframework.util.ObjectUtils; /** + * {@link AnnotationVisitor} to recursively visit annotation arrays. + * * @author Chris Beams * @author Juergen Hoeller * @since 3.1.1 @@ -80,6 +83,20 @@ class RecursiveAnnotationArrayVisitor extends AbstractRecursiveAnnotationVisitor if (!this.allNestedAttributes.isEmpty()) { this.attributes.put(this.attributeName, this.allNestedAttributes.toArray(new AnnotationAttributes[0])); } + else if (!this.attributes.containsKey(this.attributeName)) { + Class annotationType = this.attributes.annotationType(); + if (annotationType != null) { + try { + Class attributeType = annotationType.getMethod(this.attributeName).getReturnType(); + if (attributeType.isArray()) { + this.attributes.put(this.attributeName, Array.newInstance(attributeType.getComponentType(), 0)); + } + } + catch (NoSuchMethodException ex) { + // Corresponding attribute method not found: cannot expose empty array. + } + } + } } } diff --git a/spring-core/src/test/java/org/springframework/core/type/AnnotationMetadataTests.java b/spring-core/src/test/java/org/springframework/core/type/AnnotationMetadataTests.java index b20ce3f8e7..76176f817b 100644 --- a/spring-core/src/test/java/org/springframework/core/type/AnnotationMetadataTests.java +++ b/spring-core/src/test/java/org/springframework/core/type/AnnotationMetadataTests.java @@ -338,7 +338,9 @@ public class AnnotationMetadataTests { allMeta = metadata.getAllAnnotationAttributes(DirectAnnotation.class.getName()).get("value"); assertThat(new HashSet<>(allMeta), is(equalTo(new HashSet(Arrays.asList("direct", "meta"))))); allMeta = metadata.getAllAnnotationAttributes(DirectAnnotation.class.getName()).get("additional"); - assertThat(new HashSet<>(allMeta), is(equalTo(new HashSet(Arrays.asList("direct"))))); + assertThat(new HashSet<>(allMeta), is(equalTo(new HashSet(Arrays.asList("direct", ""))))); + assertEquals("", metadata.getAnnotationAttributes(DirectAnnotation.class.getName()).get("additional")); + assertEquals(0, ((String[]) metadata.getAnnotationAttributes(DirectAnnotation.class.getName()).get("additionalArray")).length); } { // perform tests with classValuesAsString = true AnnotationAttributes specialAttrs = (AnnotationAttributes) metadata.getAnnotationAttributes( @@ -425,6 +427,8 @@ public class AnnotationMetadataTests { String myValue() default ""; String additional() default "direct"; + + String[] additionalArray() default "direct"; } @Target(ElementType.TYPE) @@ -470,7 +474,7 @@ public class AnnotationMetadataTests { nestedAnno = @NestedAnno(value = "na", anEnum = SomeEnum.LABEL1, classArray = {String.class}), nestedAnnoArray = {@NestedAnno, @NestedAnno(value = "na1", anEnum = SomeEnum.LABEL2, classArray = {Number.class})}) @SuppressWarnings({"serial", "unused"}) - @DirectAnnotation("direct") + @DirectAnnotation(value = "direct", additional = "", additionalArray = {}) @MetaMetaAnnotation @EnumSubclasses({SubclassEnum.FOO, SubclassEnum.BAR}) private static class AnnotatedComponent implements Serializable {