Browse Source

Log warning for convention-based attribute overrides once per annotation type

See gh-28760, gh-29206
pull/29336/head
Sam Brannen 3 years ago
parent
commit
0e861af050
  1. 28
      spring-core/src/main/java/org/springframework/core/annotation/AnnotationTypeMapping.java
  2. 4
      spring-core/src/test/java/org/springframework/core/annotation/MergedAnnotationsTests.java

28
spring-core/src/main/java/org/springframework/core/annotation/AnnotationTypeMapping.java

@ -53,9 +53,8 @@ final class AnnotationTypeMapping {
private static final Log logger = LogFactory.getLog(AnnotationTypeMapping.class); private static final Log logger = LogFactory.getLog(AnnotationTypeMapping.class);
/** /**
* Set of fully qualified class names concatenated with attribute names for * Set of fully qualified class names for annotations which we have already
* annotations which we have already checked for use of convention-based * checked for use of convention-based annotation attribute overrides.
* annotation attribute overrides.
* @since 6.0 * @since 6.0
* @see #addConventionMappings() * @see #addConventionMappings()
*/ */
@ -284,21 +283,12 @@ final class AnnotationTypeMapping {
} }
AttributeMethods rootAttributes = this.root.getAttributes(); AttributeMethods rootAttributes = this.root.getAttributes();
int[] mappings = this.conventionMappings; int[] mappings = this.conventionMappings;
Set<String> conventionMappedAttributes = new HashSet<>();
for (int i = 0; i < mappings.length; i++) { for (int i = 0; i < mappings.length; i++) {
String name = this.attributes.get(i).getName(); String name = this.attributes.get(i).getName();
int mapped = rootAttributes.indexOf(name); int mapped = rootAttributes.indexOf(name);
if (!MergedAnnotation.VALUE.equals(name) && mapped != -1 && !isExplicitAttributeOverride(name)) { if (!MergedAnnotation.VALUE.equals(name) && mapped != -1 && !isExplicitAttributeOverride(name)) {
String rootAnnotationTypeName = this.root.annotationType.getName(); conventionMappedAttributes.add(name);
String cacheKey = rootAnnotationTypeName + "." + name;
// We want to avoid duplicate log warnings as much as possible, without full synchronization.
if (conventionBasedOverrideCheckCache.add(cacheKey) && logger.isWarnEnabled()) {
logger.warn("""
Support for convention-based annotation attribute overrides is \
deprecated and will be removed in Spring Framework 6.1. Please \
annotate the '%s' attribute in @%s with an appropriate @AliasFor \
declaration -- for example, @AliasFor(annotation = %s.class)."""
.formatted(name, rootAnnotationTypeName, this.annotationType.getName()));
}
mappings[i] = mapped; mappings[i] = mapped;
MirrorSet mirrors = getMirrorSets().getAssigned(i); MirrorSet mirrors = getMirrorSets().getAssigned(i);
if (mirrors != null) { if (mirrors != null) {
@ -308,6 +298,16 @@ final class AnnotationTypeMapping {
} }
} }
} }
String rootAnnotationTypeName = this.root.annotationType.getName();
// We want to avoid duplicate log warnings as much as possible, without full synchronization.
if (conventionBasedOverrideCheckCache.add(rootAnnotationTypeName) &&
!conventionMappedAttributes.isEmpty() && logger.isWarnEnabled()) {
logger.warn("""
Support for convention-based annotation attribute overrides is deprecated \
and will be removed in Spring Framework 6.1. Please annotate the following \
attributes in @%s with appropriate @AliasFor declarations: %s"""
.formatted(rootAnnotationTypeName, conventionMappedAttributes));
}
} }
/** /**

4
spring-core/src/test/java/org/springframework/core/annotation/MergedAnnotationsTests.java

@ -2445,6 +2445,10 @@ class MergedAnnotationsTests {
// Do NOT use @AliasFor here until Spring 6.1 // Do NOT use @AliasFor here until Spring 6.1
// @AliasFor(annotation = ContextConfiguration.class) // @AliasFor(annotation = ContextConfiguration.class)
String[] locations() default {}; String[] locations() default {};
// Do NOT use @AliasFor here until Spring 6.1
// @AliasFor(annotation = ContextConfiguration.class)
Class<?>[] classes() default {};
} }
@ContextConfiguration(value = "duplicateDeclaration") @ContextConfiguration(value = "duplicateDeclaration")

Loading…
Cancel
Save