Browse Source

Consistent exposure of empty attribute arrays in AnnotationMetadata

Issue: SPR-17347

(cherry picked from commit 83909e6e1e)
pull/1998/head
Juergen Hoeller 6 years ago
parent
commit
53430760f3
  1. 17
      spring-core/src/main/java/org/springframework/core/type/classreading/RecursiveAnnotationArrayVisitor.java
  2. 8
      spring-core/src/test/java/org/springframework/core/type/AnnotationMetadataTests.java

17
spring-core/src/main/java/org/springframework/core/type/classreading/RecursiveAnnotationArrayVisitor.java

@ -16,6 +16,7 @@ @@ -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; @@ -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 @@ -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<? extends Annotation> 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.
}
}
}
}
}

8
spring-core/src/test/java/org/springframework/core/type/AnnotationMetadataTests.java

@ -338,7 +338,9 @@ public class AnnotationMetadataTests { @@ -338,7 +338,9 @@ public class AnnotationMetadataTests {
allMeta = metadata.getAllAnnotationAttributes(DirectAnnotation.class.getName()).get("value");
assertThat(new HashSet<>(allMeta), is(equalTo(new HashSet<Object>(Arrays.asList("direct", "meta")))));
allMeta = metadata.getAllAnnotationAttributes(DirectAnnotation.class.getName()).get("additional");
assertThat(new HashSet<>(allMeta), is(equalTo(new HashSet<Object>(Arrays.asList("direct")))));
assertThat(new HashSet<>(allMeta), is(equalTo(new HashSet<Object>(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 { @@ -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 { @@ -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 {

Loading…
Cancel
Save