Merge branch '5.3.x'
This commit is contained in:
commit
c54b1519e4
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -36,6 +36,7 @@ import javax.annotation.meta.When;
|
|||
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.annotation.AnnotationUtilsTests.ExtendsBaseClassWithGenericAnnotatedMethod;
|
||||
|
|
@ -82,6 +83,90 @@ class AnnotatedElementUtilsTests {
|
|||
private static final String TX_NAME = Transactional.class.getName();
|
||||
|
||||
|
||||
@Nested
|
||||
class ConventionBasedAnnotationAttributeOverrideTests {
|
||||
|
||||
@Test
|
||||
void getMergedAnnotationAttributesWithConventionBasedComposedAnnotation() {
|
||||
Class<?> element = ConventionBasedComposedContextConfigClass.class;
|
||||
String name = ContextConfig.class.getName();
|
||||
AnnotationAttributes attributes = getMergedAnnotationAttributes(element, name);
|
||||
|
||||
assertThat(attributes).as("Should find @ContextConfig on " + element.getSimpleName()).isNotNull();
|
||||
assertThat(attributes.getStringArray("locations")).as("locations").containsExactly("explicitDeclaration");
|
||||
assertThat(attributes.getStringArray("value")).as("value").containsExactly("explicitDeclaration");
|
||||
|
||||
// Verify contracts between utility methods:
|
||||
assertThat(isAnnotated(element, name)).isTrue();
|
||||
}
|
||||
|
||||
/**
|
||||
* This test should never pass, simply because Spring does not support a hybrid
|
||||
* approach for annotation attribute overrides with transitive implicit aliases.
|
||||
* See SPR-13554 for details.
|
||||
* <p>Furthermore, if you choose to execute this test, it can fail for either
|
||||
* the first test class or the second one (with different exceptions), depending
|
||||
* on the order in which the JVM returns the attribute methods via reflection.
|
||||
*/
|
||||
@Disabled("Permanently disabled but left in place for illustrative purposes")
|
||||
@Test
|
||||
void getMergedAnnotationAttributesWithHalfConventionBasedAndHalfAliasedComposedAnnotation() {
|
||||
for (Class<?> clazz : asList(HalfConventionBasedAndHalfAliasedComposedContextConfigClassV1.class,
|
||||
HalfConventionBasedAndHalfAliasedComposedContextConfigClassV2.class)) {
|
||||
getMergedAnnotationAttributesWithHalfConventionBasedAndHalfAliasedComposedAnnotation(clazz);
|
||||
}
|
||||
}
|
||||
|
||||
private void getMergedAnnotationAttributesWithHalfConventionBasedAndHalfAliasedComposedAnnotation(Class<?> clazz) {
|
||||
String name = ContextConfig.class.getName();
|
||||
String simpleName = clazz.getSimpleName();
|
||||
AnnotationAttributes attributes = getMergedAnnotationAttributes(clazz, name);
|
||||
|
||||
assertThat(attributes).as("Should find @ContextConfig on " + simpleName).isNotNull();
|
||||
assertThat(attributes.getStringArray("locations")).as("locations for class [" + simpleName + "]")
|
||||
.containsExactly("explicitDeclaration");
|
||||
assertThat(attributes.getStringArray("value")).as("value for class [" + simpleName + "]")
|
||||
.containsExactly("explicitDeclaration");
|
||||
|
||||
// Verify contracts between utility methods:
|
||||
assertThat(isAnnotated(clazz, name)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getMergedAnnotationAttributesWithInvalidConventionBasedComposedAnnotation() {
|
||||
Class<?> element = InvalidConventionBasedComposedContextConfigClass.class;
|
||||
assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() ->
|
||||
getMergedAnnotationAttributes(element, ContextConfig.class))
|
||||
.withMessageContaining("Different @AliasFor mirror values for annotation")
|
||||
.withMessageContaining("attribute 'locations' and its alias 'value'")
|
||||
.withMessageContaining("values of [{requiredLocationsDeclaration}] and [{duplicateDeclaration}]");
|
||||
}
|
||||
|
||||
@Test
|
||||
void findMergedAnnotationAttributesWithSingleElementOverridingAnArrayViaConvention() {
|
||||
assertComponentScanAttributes(ConventionBasedSinglePackageComponentScanClass.class, "com.example.app.test");
|
||||
}
|
||||
|
||||
@Test
|
||||
void findMergedAnnotationWithLocalAliasesThatConflictWithAttributesInMetaAnnotationByConvention() {
|
||||
Class<?> element = SpringAppConfigClass.class;
|
||||
ContextConfig contextConfig = findMergedAnnotation(element, ContextConfig.class);
|
||||
|
||||
assertThat(contextConfig).as("Should find @ContextConfig on " + element).isNotNull();
|
||||
assertThat(contextConfig.locations()).as("locations for " + element).isEmpty();
|
||||
// 'value' in @SpringAppConfig should not override 'value' in @ContextConfig
|
||||
assertThat(contextConfig.value()).as("value for " + element).isEmpty();
|
||||
assertThat(contextConfig.classes()).as("classes for " + element).containsExactly(Number.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void findMergedAnnotationWithSingleElementOverridingAnArrayViaConvention() throws Exception {
|
||||
assertWebMapping(WebController.class.getMethod("postMappedWithPathAttribute"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void getMetaAnnotationTypesOnNonAnnotatedClass() {
|
||||
assertThat(getMetaAnnotationTypes(NonAnnotatedClass.class, TransactionalComponent.class).isEmpty()).isTrue();
|
||||
|
|
@ -363,51 +448,6 @@ class AnnotatedElementUtilsTests {
|
|||
assertThat(isAnnotated(element, name)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getMergedAnnotationAttributesWithConventionBasedComposedAnnotation() {
|
||||
Class<?> element = ConventionBasedComposedContextConfigClass.class;
|
||||
String name = ContextConfig.class.getName();
|
||||
AnnotationAttributes attributes = getMergedAnnotationAttributes(element, name);
|
||||
|
||||
assertThat(attributes).as("Should find @ContextConfig on " + element.getSimpleName()).isNotNull();
|
||||
assertThat(attributes.getStringArray("locations")).as("locations").isEqualTo(asArray("explicitDeclaration"));
|
||||
assertThat(attributes.getStringArray("value")).as("value").isEqualTo(asArray("explicitDeclaration"));
|
||||
|
||||
// Verify contracts between utility methods:
|
||||
assertThat(isAnnotated(element, name)).isTrue();
|
||||
}
|
||||
|
||||
/**
|
||||
* This test should never pass, simply because Spring does not support a hybrid
|
||||
* approach for annotation attribute overrides with transitive implicit aliases.
|
||||
* See SPR-13554 for details.
|
||||
* <p>Furthermore, if you choose to execute this test, it can fail for either
|
||||
* the first test class or the second one (with different exceptions), depending
|
||||
* on the order in which the JVM returns the attribute methods via reflection.
|
||||
*/
|
||||
@Disabled("Permanently disabled but left in place for illustrative purposes")
|
||||
@Test
|
||||
void getMergedAnnotationAttributesWithHalfConventionBasedAndHalfAliasedComposedAnnotation() {
|
||||
for (Class<?> clazz : asList(HalfConventionBasedAndHalfAliasedComposedContextConfigClassV1.class,
|
||||
HalfConventionBasedAndHalfAliasedComposedContextConfigClassV2.class)) {
|
||||
getMergedAnnotationAttributesWithHalfConventionBasedAndHalfAliasedComposedAnnotation(clazz);
|
||||
}
|
||||
}
|
||||
|
||||
private void getMergedAnnotationAttributesWithHalfConventionBasedAndHalfAliasedComposedAnnotation(Class<?> clazz) {
|
||||
String[] expected = asArray("explicitDeclaration");
|
||||
String name = ContextConfig.class.getName();
|
||||
String simpleName = clazz.getSimpleName();
|
||||
AnnotationAttributes attributes = getMergedAnnotationAttributes(clazz, name);
|
||||
|
||||
assertThat(attributes).as("Should find @ContextConfig on " + simpleName).isNotNull();
|
||||
assertThat(attributes.getStringArray("locations")).as("locations for class [" + clazz.getSimpleName() + "]").isEqualTo(expected);
|
||||
assertThat(attributes.getStringArray("value")).as("value for class [" + clazz.getSimpleName() + "]").isEqualTo(expected);
|
||||
|
||||
// Verify contracts between utility methods:
|
||||
assertThat(isAnnotated(clazz, name)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getMergedAnnotationAttributesWithAliasedComposedAnnotation() {
|
||||
Class<?> element = AliasedComposedContextConfigClass.class;
|
||||
|
|
@ -530,16 +570,6 @@ class AnnotatedElementUtilsTests {
|
|||
assertThat(isAnnotated(element, name)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getMergedAnnotationAttributesWithInvalidConventionBasedComposedAnnotation() {
|
||||
Class<?> element = InvalidConventionBasedComposedContextConfigClass.class;
|
||||
assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() ->
|
||||
getMergedAnnotationAttributes(element, ContextConfig.class))
|
||||
.withMessageContaining("Different @AliasFor mirror values for annotation")
|
||||
.withMessageContaining("attribute 'locations' and its alias 'value'")
|
||||
.withMessageContaining("values of [{requiredLocationsDeclaration}] and [{duplicateDeclaration}]");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getMergedAnnotationAttributesWithShadowedAliasComposedAnnotation() {
|
||||
Class<?> element = ShadowedAliasComposedContextConfigClass.class;
|
||||
|
|
@ -743,11 +773,6 @@ class AnnotatedElementUtilsTests {
|
|||
assertThat(annotation.qualifier()).as("TX qualifier for " + clazz).isEqualTo("anotherTransactionManager");
|
||||
}
|
||||
|
||||
@Test
|
||||
void findMergedAnnotationAttributesWithSingleElementOverridingAnArrayViaConvention() {
|
||||
assertComponentScanAttributes(ConventionBasedSinglePackageComponentScanClass.class, "com.example.app.test");
|
||||
}
|
||||
|
||||
@Test
|
||||
void findMergedAnnotationAttributesWithSingleElementOverridingAnArrayViaAliasFor() {
|
||||
assertComponentScanAttributes(AliasForBasedSinglePackageComponentScanClass.class, "com.example.app.test");
|
||||
|
|
@ -800,24 +825,6 @@ class AnnotatedElementUtilsTests {
|
|||
assertThat(testPropSource.value()).as("value").isEqualTo(propFiles);
|
||||
}
|
||||
|
||||
@Test
|
||||
void findMergedAnnotationWithLocalAliasesThatConflictWithAttributesInMetaAnnotationByConvention() {
|
||||
final String[] EMPTY = new String[0];
|
||||
Class<?> element = SpringAppConfigClass.class;
|
||||
ContextConfig contextConfig = findMergedAnnotation(element, ContextConfig.class);
|
||||
|
||||
assertThat(contextConfig).as("Should find @ContextConfig on " + element).isNotNull();
|
||||
assertThat(contextConfig.locations()).as("locations for " + element).isEqualTo(EMPTY);
|
||||
// 'value' in @SpringAppConfig should not override 'value' in @ContextConfig
|
||||
assertThat(contextConfig.value()).as("value for " + element).isEqualTo(EMPTY);
|
||||
assertThat(contextConfig.classes()).as("classes for " + element).isEqualTo(new Class<?>[] {Number.class});
|
||||
}
|
||||
|
||||
@Test
|
||||
void findMergedAnnotationWithSingleElementOverridingAnArrayViaConvention() throws Exception {
|
||||
assertWebMapping(WebController.class.getMethod("postMappedWithPathAttribute"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void findMergedAnnotationWithSingleElementOverridingAnArrayViaAliasFor() throws Exception {
|
||||
assertWebMapping(WebController.class.getMethod("getMappedWithValueAttribute"));
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ class MergedAnnotationsTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
void withInheritedAnnotationsFromHalfConventionBasedAndHalfAliasedComposedAnnotation2() {
|
||||
void getWithInheritedAnnotationsFromHalfConventionBasedAndHalfAliasedComposedAnnotation2() {
|
||||
// SPR-13554: convention mapping mixed with AliasFor annotations
|
||||
// locations doesn't apply because it has no AliasFor annotation
|
||||
MergedAnnotation<?> annotation =
|
||||
|
|
|
|||
Loading…
Reference in New Issue