Skip to content

Commit 5ac8680

Browse files
committed
Clarified getAllAnnotationAttributes behavior
Issue: SPR-12473
1 parent 58bea23 commit 5ac8680

File tree

2 files changed

+31
-22
lines changed

2 files changed

+31
-22
lines changed

spring-core/src/main/java/org/springframework/core/type/AnnotatedTypeMetadata.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@
3838
public interface AnnotatedTypeMetadata {
3939

4040
/**
41-
* Determine whether the underlying type has an annotation or
42-
* meta-annotation of the given type defined.
41+
* Determine whether the underlying element has an annotation or meta-annotation
42+
* of the given type defined.
4343
* <p>If this method returns {@code true}, then
4444
* {@link #getAnnotationAttributes} will return a non-null Map.
4545
* @param annotationType the annotation type to look for
@@ -48,9 +48,9 @@ public interface AnnotatedTypeMetadata {
4848
boolean isAnnotated(String annotationType);
4949

5050
/**
51-
* Retrieve the attributes of the annotation of the given type,
52-
* if any (i.e. if defined on the underlying class, as direct
53-
* annotation or as meta-annotation).
51+
* Retrieve the attributes of the annotation of the given type, if any (i.e. if
52+
* defined on the underlying element, as direct annotation or meta-annotation),
53+
* also taking attribute overrides on composed annotations into account.
5454
* @param annotationType the annotation type to look for
5555
* @return a Map of attributes, with the attribute name as key (e.g. "value")
5656
* and the defined attribute value as Map value. This return value will be
@@ -59,9 +59,9 @@ public interface AnnotatedTypeMetadata {
5959
Map<String, Object> getAnnotationAttributes(String annotationType);
6060

6161
/**
62-
* Retrieve the attributes of the annotation of the given type,
63-
* if any (i.e. if defined on the underlying class, as direct
64-
* annotation or as meta-annotation).
62+
* Retrieve the attributes of the annotation of the given type, if any (i.e. if
63+
* defined on the underlying element, as direct annotation or meta-annotation),
64+
* also taking attribute overrides on composed annotations into account.
6565
* @param annotationType the annotation type to look for
6666
* @param classValuesAsString whether to convert class references to String
6767
* class names for exposure as values in the returned Map, instead of Class
@@ -74,8 +74,8 @@ public interface AnnotatedTypeMetadata {
7474

7575
/**
7676
* Retrieve all attributes of all annotations of the given type, if any (i.e. if
77-
* defined on the underlying type ({@link AnnotationMetadata class} or
78-
* {@link MethodMetadata method}), as direct annotation or as meta-annotation).
77+
* defined on the underlying element, as direct annotation or meta-annotation).
78+
* Note that this variant does <i>not</i> take attribute overrides into account.
7979
* @param annotationType the annotation type to look for
8080
* @return a MultiMap of attributes, with the attribute name as key (e.g. "value")
8181
* and a list of the defined attribute values as Map value. This return value will
@@ -86,8 +86,8 @@ public interface AnnotatedTypeMetadata {
8686

8787
/**
8888
* Retrieve all attributes of all annotations of the given type, if any (i.e. if
89-
* defined on the underlying type ({@link AnnotationMetadata class} or
90-
* {@link MethodMetadata method}), as direct annotation or as meta-annotation).
89+
* defined on the underlying element, as direct annotation or meta-annotation).
90+
* Note that this variant does <i>not</i> take attribute overrides into account.
9191
* @param annotationType the annotation type to look for
9292
* @param classValuesAsString whether to convert class references to String
9393
* @return a MultiMap of attributes, with the attribute name as key (e.g. "value")

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

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ public void composedAnnotationWithMetaAnnotationsWithIdenticalAttributeNamesUsin
164164
assertMultipleAnnotationsWithIdenticalAttributeNames(metadata);
165165
}
166166

167+
167168
private void assertMultipleAnnotationsWithIdenticalAttributeNames(AnnotationMetadata metadata) {
168169
AnnotationAttributes attributes1 = (AnnotationAttributes) metadata.getAnnotationAttributes(
169170
NamedAnnotation1.class.getName(), false);
@@ -211,6 +212,8 @@ private void doTestAnnotationInfo(AnnotationMetadata metadata) {
211212
assertEquals("direct", method.getAnnotationAttributes(DirectAnnotation.class.getName()).get("value"));
212213
List<Object> allMeta = method.getAllAnnotationAttributes(DirectAnnotation.class.getName()).get("value");
213214
assertThat(new HashSet<Object>(allMeta), is(equalTo(new HashSet<Object>(Arrays.asList("direct", "meta")))));
215+
allMeta = method.getAllAnnotationAttributes(DirectAnnotation.class.getName()).get("additional");
216+
assertThat(new HashSet<Object>(allMeta), is(equalTo(new HashSet<Object>(Arrays.asList("direct")))));
214217

215218
assertTrue(metadata.isAnnotated(IsAnnotatedAnnotation.class.getName()));
216219

@@ -251,6 +254,8 @@ private void doTestAnnotationInfo(AnnotationMetadata metadata) {
251254
assertEquals("direct", metadata.getAnnotationAttributes(DirectAnnotation.class.getName()).get("value"));
252255
allMeta = metadata.getAllAnnotationAttributes(DirectAnnotation.class.getName()).get("value");
253256
assertThat(new HashSet<Object>(allMeta), is(equalTo(new HashSet<Object>(Arrays.asList("direct", "meta")))));
257+
allMeta = metadata.getAllAnnotationAttributes(DirectAnnotation.class.getName()).get("additional");
258+
assertThat(new HashSet<Object>(allMeta), is(equalTo(new HashSet<Object>(Arrays.asList("direct")))));
254259
}
255260
{ // perform tests with classValuesAsString = true
256261
AnnotationAttributes specialAttrs = (AnnotationAttributes) metadata.getAnnotationAttributes(
@@ -341,14 +346,16 @@ public static enum SomeEnum {
341346
NestedAnno[] optionalArray() default { @NestedAnno(value = "optional", anEnum = SomeEnum.DEFAULT, classArray = Void.class) };
342347
}
343348

344-
@Target({ ElementType.TYPE, ElementType.METHOD })
349+
@Target({ElementType.TYPE, ElementType.METHOD})
345350
@Retention(RetentionPolicy.RUNTIME)
346351
public @interface DirectAnnotation {
347352

348353
String value();
354+
355+
String additional() default "direct";
349356
}
350357

351-
@Target({ ElementType.TYPE })
358+
@Target(ElementType.TYPE)
352359
@Retention(RetentionPolicy.RUNTIME)
353360
public @interface IsAnnotatedAnnotation {
354361
}
@@ -358,9 +365,11 @@ public static enum SomeEnum {
358365
@DirectAnnotation("meta")
359366
@IsAnnotatedAnnotation
360367
public @interface MetaAnnotation {
368+
369+
String additional() default "meta";
361370
}
362371

363-
@Target({ ElementType.TYPE, ElementType.METHOD })
372+
@Target({ElementType.TYPE, ElementType.METHOD})
364373
@Retention(RetentionPolicy.RUNTIME)
365374
@MetaAnnotation
366375
public @interface MetaMetaAnnotation {
@@ -380,17 +389,18 @@ public static enum SubclassEnum {
380389
},
381390
BAR {
382391
/* Do not delete! This subclassing is intentional. */
383-
};
392+
}
384393
}
385394

386395
@Component("myName")
387396
@Scope("myScope")
388-
@SpecialAttr(clazz = String.class, state = Thread.State.NEW, nestedAnno = @NestedAnno(value = "na", anEnum = SomeEnum.LABEL1, classArray = { String.class }), nestedAnnoArray = {
389-
@NestedAnno, @NestedAnno(value = "na1", anEnum = SomeEnum.LABEL2, classArray = { Number.class }) })
390-
@SuppressWarnings({ "serial", "unused" })
397+
@SpecialAttr(clazz = String.class, state = Thread.State.NEW,
398+
nestedAnno = @NestedAnno(value = "na", anEnum = SomeEnum.LABEL1, classArray = {String.class}),
399+
nestedAnnoArray = {@NestedAnno, @NestedAnno(value = "na1", anEnum = SomeEnum.LABEL2, classArray = {Number.class})})
400+
@SuppressWarnings({"serial", "unused"})
391401
@DirectAnnotation("direct")
392402
@MetaMetaAnnotation
393-
@EnumSubclasses({ SubclassEnum.FOO, SubclassEnum.BAR })
403+
@EnumSubclasses({SubclassEnum.FOO, SubclassEnum.BAR})
394404
private static class AnnotatedComponent implements Serializable {
395405

396406
@TestAutowired
@@ -406,9 +416,8 @@ public void meta() {
406416
}
407417
}
408418

409-
@SuppressWarnings({ "serial" })
419+
@SuppressWarnings("serial")
410420
private static class AnnotatedComponentSubClass extends AnnotatedComponent {
411-
412421
}
413422

414423
@Target(ElementType.TYPE)

0 commit comments

Comments
 (0)