From f44217a0c2f13e5a1eb52001d7c7ef3bb515d40b Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 26 Nov 2014 15:35:24 +0100 Subject: [PATCH] Clarified getAllAnnotationAttributes behavior Issue: SPR-12473 (cherry picked from commit 5ac8680) --- .../core/type/AnnotatedTypeMetadata.java | 24 ++++++++--------- .../core/type/AnnotationMetadataTests.java | 26 +++++++++++++------ 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/core/type/AnnotatedTypeMetadata.java b/spring-core/src/main/java/org/springframework/core/type/AnnotatedTypeMetadata.java index 802896d0b7..be7e31d2c3 100644 --- a/spring-core/src/main/java/org/springframework/core/type/AnnotatedTypeMetadata.java +++ b/spring-core/src/main/java/org/springframework/core/type/AnnotatedTypeMetadata.java @@ -38,8 +38,8 @@ import org.springframework.util.MultiValueMap; public interface AnnotatedTypeMetadata { /** - * Determine whether the underlying type has an annotation or - * meta-annotation of the given type defined. + * Determine whether the underlying element has an annotation or meta-annotation + * of the given type defined. *

If this method returns {@code true}, then * {@link #getAnnotationAttributes} will return a non-null Map. * @param annotationType the annotation type to look for @@ -48,9 +48,9 @@ public interface AnnotatedTypeMetadata { boolean isAnnotated(String annotationType); /** - * Retrieve the attributes of the annotation of the given type, - * if any (i.e. if defined on the underlying class, as direct - * annotation or as meta-annotation). + * Retrieve the attributes of the annotation of the given type, if any (i.e. if + * defined on the underlying element, as direct annotation or meta-annotation), + * also taking attribute overrides on composed annotations into account. * @param annotationType the annotation type to look for * @return a Map of attributes, with the attribute name as key (e.g. "value") * and the defined attribute value as Map value. This return value will be @@ -59,9 +59,9 @@ public interface AnnotatedTypeMetadata { Map getAnnotationAttributes(String annotationType); /** - * Retrieve the attributes of the annotation of the given type, - * if any (i.e. if defined on the underlying class, as direct - * annotation or as meta-annotation). + * Retrieve the attributes of the annotation of the given type, if any (i.e. if + * defined on the underlying element, as direct annotation or meta-annotation), + * also taking attribute overrides on composed annotations into account. * @param annotationType the annotation type to look for * @param classValuesAsString whether to convert class references to String * class names for exposure as values in the returned Map, instead of Class @@ -74,8 +74,8 @@ public interface AnnotatedTypeMetadata { /** * Retrieve all attributes of all annotations of the given type, if any (i.e. if - * defined on the underlying type ({@link AnnotationMetadata class} or - * {@link MethodMetadata method}), as direct annotation or as meta-annotation). + * defined on the underlying element, as direct annotation or meta-annotation). + * Note that this variant does not take attribute overrides into account. * @param annotationType the annotation type to look for * @return a MultiMap of attributes, with the attribute name as key (e.g. "value") * and a list of the defined attribute values as Map value. This return value will @@ -86,8 +86,8 @@ public interface AnnotatedTypeMetadata { /** * Retrieve all attributes of all annotations of the given type, if any (i.e. if - * defined on the underlying type ({@link AnnotationMetadata class} or - * {@link MethodMetadata method}), as direct annotation or as meta-annotation). + * defined on the underlying element, as direct annotation or meta-annotation). + * Note that this variant does not take attribute overrides into account. * @param annotationType the annotation type to look for * @param classValuesAsString whether to convert class references to String * @return a MultiMap of attributes, with the attribute name as key (e.g. "value") 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 92ebc8735c..78f32d9ee4 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 @@ -244,6 +244,7 @@ public class AnnotationMetadataTests { assertMultipleAnnotationsWithIdenticalAttributeNames(metadata); } + private void assertMultipleAnnotationsWithIdenticalAttributeNames(AnnotationMetadata metadata) { AnnotationAttributes attributes1 = (AnnotationAttributes) metadata.getAnnotationAttributes( NamedAnnotation1.class.getName(), false); @@ -292,6 +293,8 @@ public class AnnotationMetadataTests { assertEquals("direct", method.getAnnotationAttributes(DirectAnnotation.class.getName()).get("value")); List allMeta = method.getAllAnnotationAttributes(DirectAnnotation.class.getName()).get("value"); assertThat(new HashSet(allMeta), is(equalTo(new HashSet(Arrays.asList("direct", "meta"))))); + allMeta = method.getAllAnnotationAttributes(DirectAnnotation.class.getName()).get("additional"); + assertThat(new HashSet(allMeta), is(equalTo(new HashSet(Arrays.asList("direct"))))); assertTrue(metadata.isAnnotated(IsAnnotatedAnnotation.class.getName())); @@ -332,6 +335,8 @@ public class AnnotationMetadataTests { assertEquals("direct", metadata.getAnnotationAttributes(DirectAnnotation.class.getName()).get("value")); 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"))))); } { // perform tests with classValuesAsString = true AnnotationAttributes specialAttrs = (AnnotationAttributes) metadata.getAnnotationAttributes( @@ -407,14 +412,16 @@ public class AnnotationMetadataTests { NestedAnno[] optionalArray() default { @NestedAnno(value = "optional", anEnum = SomeEnum.DEFAULT, classArray = Void.class) }; } - @Target({ ElementType.TYPE, ElementType.METHOD }) + @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface DirectAnnotation { String value(); + + String additional() default "direct"; } - @Target({ ElementType.TYPE }) + @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface IsAnnotatedAnnotation { } @@ -424,9 +431,11 @@ public class AnnotationMetadataTests { @DirectAnnotation("meta") @IsAnnotatedAnnotation public @interface MetaAnnotation { + + String additional() default "meta"; } - @Target({ ElementType.TYPE, ElementType.METHOD }) + @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @MetaAnnotation public @interface MetaMetaAnnotation { @@ -446,17 +455,18 @@ public class AnnotationMetadataTests { }, BAR { /* Do not delete! This subclassing is intentional. */ - }; + } } @Component("myName") @Scope("myScope") - @SpecialAttr(clazz = String.class, state = Thread.State.NEW, nestedAnno = @NestedAnno(value = "na", anEnum = SomeEnum.LABEL1, classArray = { String.class }), nestedAnnoArray = { - @NestedAnno, @NestedAnno(value = "na1", anEnum = SomeEnum.LABEL2, classArray = { Number.class }) }) - @SuppressWarnings({ "serial", "unused" }) + @SpecialAttr(clazz = String.class, state = Thread.State.NEW, + 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") @MetaMetaAnnotation - @EnumSubclasses({ SubclassEnum.FOO, SubclassEnum.BAR }) + @EnumSubclasses({SubclassEnum.FOO, SubclassEnum.BAR}) private static class AnnotatedComponent implements Serializable { @TestAutowired -- GitLab