Ensure @AliasFor overrides attribute in correct meta-annotation
Prior to this commit, an explicit override for an attribute in a meta-annotation configured via @AliasFor could potentially result in an incorrect override of an attribute of the same name but in the wrong meta-annotation. This commit fixes the algorithm in getAliasedAttributeName(Method, Class) in AnnotationUtils by ensuring that an explicit attribute override is only applied to the configured target meta-annotation (i.e., configured via the 'annotation' attribute in @AliasFor). Issue: SPR-13325
This commit is contained in:
@@ -491,6 +491,30 @@ public class AnnotatedElementUtilsTests {
|
||||
assertEquals("TX qualifier via synthesized annotation.", "aliasForQualifier", annotation.qualifier());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findMergedAnnotationForMultipleMetaAnnotationsWithClashingAttributeNames() {
|
||||
final String[] xmlLocations = new String[] { "test.xml" };
|
||||
final String[] propFiles = new String[] { "test.properties" };
|
||||
|
||||
Class<?> element = AliasedComposedContextConfigAndTestPropSourceClass.class;
|
||||
|
||||
ContextConfig contextConfig = findMergedAnnotation(element, ContextConfig.class);
|
||||
assertNotNull("@ContextConfig on " + element, contextConfig);
|
||||
assertArrayEquals("locations", xmlLocations, contextConfig.locations());
|
||||
assertArrayEquals("value", xmlLocations, contextConfig.value());
|
||||
|
||||
// Synthesized annotation
|
||||
TestPropSource testPropSource = AnnotationUtils.findAnnotation(element, TestPropSource.class);
|
||||
assertArrayEquals("locations", propFiles, testPropSource.locations());
|
||||
assertArrayEquals("value", propFiles, testPropSource.value());
|
||||
|
||||
// Merged annotation
|
||||
testPropSource = findMergedAnnotation(element, TestPropSource.class);
|
||||
assertNotNull("@TestPropSource on " + element, testPropSource);
|
||||
assertArrayEquals("locations", propFiles, testPropSource.locations());
|
||||
assertArrayEquals("value", propFiles, testPropSource.value());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findMergedAnnotationAttributesOnClassWithAttributeAliasInComposedAnnotationAndNestedAnnotationsInTargetAnnotation() {
|
||||
Class<?> element = TestComponentScanClass.class;
|
||||
@@ -622,6 +646,19 @@ public class AnnotatedElementUtilsTests {
|
||||
@interface MetaAndLocalTxConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock of {@code org.springframework.test.context.TestPropertySource}.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface TestPropSource {
|
||||
|
||||
@AliasFor("locations")
|
||||
String[] value() default {};
|
||||
|
||||
@AliasFor("value")
|
||||
String[] locations() default {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock of {@code org.springframework.test.context.ContextConfiguration}.
|
||||
*/
|
||||
@@ -679,6 +716,15 @@ public class AnnotatedElementUtilsTests {
|
||||
String[] xmlConfigFiles();
|
||||
}
|
||||
|
||||
@ContextConfig(locations = "shadowed.xml")
|
||||
@TestPropSource(locations = "test.properties")
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface AliasedComposedContextConfigAndTestPropSource {
|
||||
|
||||
@AliasFor(annotation = ContextConfig.class, attribute = "locations")
|
||||
String[] xmlConfigFiles() default "default.xml";
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock of {@code org.springframework.context.annotation.ComponentScan}
|
||||
*/
|
||||
@@ -855,6 +901,10 @@ public class AnnotatedElementUtilsTests {
|
||||
static class InvalidAliasedComposedContextConfigClass {
|
||||
}
|
||||
|
||||
@AliasedComposedContextConfigAndTestPropSource(xmlConfigFiles = "test.xml")
|
||||
static class AliasedComposedContextConfigAndTestPropSourceClass {
|
||||
}
|
||||
|
||||
@TestComponentScan(packages = "com.example.app.test")
|
||||
static class TestComponentScanClass {
|
||||
}
|
||||
|
||||
@@ -675,6 +675,13 @@ public class AnnotationUtilsTests {
|
||||
assertThat(set.size(), is(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAliasedAttributeNameFromWrongTargetAnnotation() throws Exception {
|
||||
Method attribute = AliasedComposedContextConfig.class.getDeclaredMethod("xmlConfigFile");
|
||||
assertNull("xmlConfigFile is not an alias for @Component.",
|
||||
getAliasedAttributeName(attribute, Component.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAliasedAttributeNameFromAliasedComposedAnnotation() throws Exception {
|
||||
Method attribute = AliasedComposedContextConfig.class.getDeclaredMethod("xmlConfigFile");
|
||||
|
||||
Reference in New Issue
Block a user