2828import java .util .Set ;
2929
3030import org .junit .Test ;
31+
3132import org .springframework .core .annotation .AnnotationAttributes ;
3233import org .springframework .core .type .classreading .MetadataReader ;
3334import org .springframework .core .type .classreading .MetadataReaderFactory ;
3435import org .springframework .core .type .classreading .SimpleMetadataReaderFactory ;
3536import org .springframework .stereotype .Component ;
36- import org .springframework .util .MultiValueMap ;
3737
3838import static org .hamcrest .CoreMatchers .*;
3939import static org .junit .Assert .*;
@@ -112,23 +112,7 @@ public void metaAnnotationOverridesUsingAnnotationMetadataReadingVisitor() throw
112112 assertMetaAnnotationOverrides (metadata );
113113 }
114114
115- /**
116- * @param metadata the metadata for {@link ComposedConfigurationWithAttributeOverridesClass}
117- */
118115 private void assertMetaAnnotationOverrides (AnnotationMetadata metadata ) {
119- assertAllAttributesForMetaAnnotationOverrides (metadata );
120- assertAttributesForMetaAnnotationOverrides (metadata );
121-
122- // SPR-11710: Invoke a 2nd time after invoking getAnnotationAttributes() in order
123- // to ensure that getMergedAnnotationAttributes() in AnnotationReadingVisitorUtils
124- // does not mutate the state of the metadata.
125- assertAllAttributesForMetaAnnotationOverrides (metadata );
126- }
127-
128- /**
129- * @param metadata the metadata for {@link ComposedConfigurationWithAttributeOverridesClass}
130- */
131- private void assertAttributesForMetaAnnotationOverrides (AnnotationMetadata metadata ) {
132116 AnnotationAttributes attributes = (AnnotationAttributes ) metadata .getAnnotationAttributes (
133117 TestComponentScan .class .getName (), false );
134118 String [] basePackages = attributes .getStringArray ("basePackages" );
@@ -141,27 +125,60 @@ private void assertAttributesForMetaAnnotationOverrides(AnnotationMetadata metad
141125 }
142126
143127 /**
144- * @param metadata the metadata for {@link ComposedConfigurationWithAttributeOverridesClass}
128+ * https://jira.spring.io/browse/SPR-11649
145129 */
146- private void assertAllAttributesForMetaAnnotationOverrides (AnnotationMetadata metadata ) {
147- MultiValueMap <String , Object > map = metadata .getAllAnnotationAttributes (TestComponentScan .class .getName ());
148- List <Object > basePackages = map .get ("basePackages" );
149- assertThat ("length of basePackages list" , basePackages .size (), is (1 ));
130+ @ Test
131+ public void multipleAnnotationsWithIdenticalAttributeNamesUsingStandardAnnotationMetadata () {
132+ AnnotationMetadata metadata = new StandardAnnotationMetadata (NamedAnnotationsClass .class );
133+ assertMultipleAnnotationsWithIdenticalAttributeNames (metadata );
134+ }
150135
151- // Ideally, the expected base package should be "org.example.componentscan", but
152- // since Spring's annotation processing currently does not support meta-annotation
153- // attribute overrides when searching for "all attributes", the actual value found
154- // is "bogus".
155- String expectedBasePackage = "bogus" ;
156- assertThat ("basePackages[0]" , ((String []) basePackages .get (0 ))[0 ], is (expectedBasePackage ));
136+ /**
137+ * https://jira.spring.io/browse/SPR-11649
138+ */
139+ @ Test
140+ public void multipleAnnotationsWithIdenticalAttributeNamesUsingAnnotationMetadataReadingVisitor () throws Exception {
141+ MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory ();
142+ MetadataReader metadataReader = metadataReaderFactory .getMetadataReader (NamedAnnotationsClass .class .getName ());
143+ AnnotationMetadata metadata = metadataReader .getAnnotationMetadata ();
144+ assertMultipleAnnotationsWithIdenticalAttributeNames (metadata );
145+ }
157146
158- List <Object > value = map .get ("value" );
159- assertThat ("length of value list" , value .size (), is (1 ));
160- assertThat ("length of 0th value array" , ((String []) value .get (0 )).length , is (0 ));
147+ /**
148+ * https://jira.spring.io/browse/SPR-11649
149+ */
150+ @ Test
151+ public void composedAnnotationWithMetaAnnotationsWithIdenticalAttributeNamesUsingStandardAnnotationMetadata () {
152+ AnnotationMetadata metadata = new StandardAnnotationMetadata (NamedComposedAnnotationClass .class );
153+ assertMultipleAnnotationsWithIdenticalAttributeNames (metadata );
154+ }
161155
162- List <Object > basePackageClasses = map .get ("basePackageClasses" );
163- assertThat ("length of basePackageClasses list" , basePackageClasses .size (), is (1 ));
164- assertThat ("length of 0th basePackageClasses array" , ((Class <?>[]) basePackageClasses .get (0 )).length , is (0 ));
156+ /**
157+ * https://jira.spring.io/browse/SPR-11649
158+ */
159+ @ Test
160+ public void composedAnnotationWithMetaAnnotationsWithIdenticalAttributeNamesUsingAnnotationMetadataReadingVisitor () throws Exception {
161+ MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory ();
162+ MetadataReader metadataReader = metadataReaderFactory .getMetadataReader (NamedComposedAnnotationClass .class .getName ());
163+ AnnotationMetadata metadata = metadataReader .getAnnotationMetadata ();
164+ assertMultipleAnnotationsWithIdenticalAttributeNames (metadata );
165+ }
166+
167+ private void assertMultipleAnnotationsWithIdenticalAttributeNames (AnnotationMetadata metadata ) {
168+ AnnotationAttributes attributes1 = (AnnotationAttributes ) metadata .getAnnotationAttributes (
169+ NamedAnnotation1 .class .getName (), false );
170+ String name1 = attributes1 .getString ("name" );
171+ assertThat ("name of NamedAnnotation1" , name1 , is ("name 1" ));
172+
173+ AnnotationAttributes attributes2 = (AnnotationAttributes ) metadata .getAnnotationAttributes (
174+ NamedAnnotation2 .class .getName (), false );
175+ String name2 = attributes2 .getString ("name" );
176+ assertThat ("name of NamedAnnotation2" , name2 , is ("name 2" ));
177+
178+ AnnotationAttributes attributes3 = (AnnotationAttributes ) metadata .getAnnotationAttributes (
179+ NamedAnnotation3 .class .getName (), false );
180+ String name3 = attributes3 .getString ("name" );
181+ assertThat ("name of NamedAnnotation3" , name3 , is ("name 3" ));
165182 }
166183
167184 private void doTestAnnotationInfo (AnnotationMetadata metadata ) {
@@ -389,6 +406,7 @@ public void meta() {
389406 }
390407 }
391408
409+ @ SuppressWarnings ({ "serial" })
392410 private static class AnnotatedComponentSubClass extends AnnotatedComponent {
393411
394412 }
@@ -425,4 +443,40 @@ private static class AnnotatedComponentSubClass extends AnnotatedComponent {
425443 public static class ComposedConfigurationWithAttributeOverridesClass {
426444 }
427445
446+ @ Retention (RetentionPolicy .RUNTIME )
447+ @ Target (ElementType .TYPE )
448+ public static @interface NamedAnnotation1 {
449+ String name () default "" ;
450+ }
451+
452+ @ Retention (RetentionPolicy .RUNTIME )
453+ @ Target (ElementType .TYPE )
454+ public static @interface NamedAnnotation2 {
455+ String name () default "" ;
456+ }
457+
458+ @ Retention (RetentionPolicy .RUNTIME )
459+ @ Target (ElementType .TYPE )
460+ public static @interface NamedAnnotation3 {
461+ String name () default "" ;
462+ }
463+
464+ @ NamedAnnotation1 (name = "name 1" )
465+ @ NamedAnnotation2 (name = "name 2" )
466+ @ NamedAnnotation3 (name = "name 3" )
467+ public static class NamedAnnotationsClass {
468+ }
469+
470+ @ NamedAnnotation1 (name = "name 1" )
471+ @ NamedAnnotation2 (name = "name 2" )
472+ @ NamedAnnotation3 (name = "name 3" )
473+ @ Retention (RetentionPolicy .RUNTIME )
474+ @ Target (ElementType .TYPE )
475+ public static @interface NamedComposedAnnotation {
476+ }
477+
478+ @ NamedComposedAnnotation
479+ public static class NamedComposedAnnotationClass {
480+ }
481+
428482}
0 commit comments