Skip to content

Commit 0e861af

Browse files
committed
Log warning for convention-based attribute overrides once per annotation type
See gh-28760, gh-29206
1 parent 5cb3af7 commit 0e861af

File tree

2 files changed

+18
-14
lines changed

2 files changed

+18
-14
lines changed

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

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,8 @@ final class AnnotationTypeMapping {
5353
private static final Log logger = LogFactory.getLog(AnnotationTypeMapping.class);
5454

5555
/**
56-
* Set of fully qualified class names concatenated with attribute names for
57-
* annotations which we have already checked for use of convention-based
58-
* annotation attribute overrides.
56+
* Set of fully qualified class names for annotations which we have already
57+
* checked for use of convention-based annotation attribute overrides.
5958
* @since 6.0
6059
* @see #addConventionMappings()
6160
*/
@@ -284,21 +283,12 @@ private void addConventionMappings() {
284283
}
285284
AttributeMethods rootAttributes = this.root.getAttributes();
286285
int[] mappings = this.conventionMappings;
286+
Set<String> conventionMappedAttributes = new HashSet<>();
287287
for (int i = 0; i < mappings.length; i++) {
288288
String name = this.attributes.get(i).getName();
289289
int mapped = rootAttributes.indexOf(name);
290290
if (!MergedAnnotation.VALUE.equals(name) && mapped != -1 && !isExplicitAttributeOverride(name)) {
291-
String rootAnnotationTypeName = this.root.annotationType.getName();
292-
String cacheKey = rootAnnotationTypeName + "." + name;
293-
// We want to avoid duplicate log warnings as much as possible, without full synchronization.
294-
if (conventionBasedOverrideCheckCache.add(cacheKey) && logger.isWarnEnabled()) {
295-
logger.warn("""
296-
Support for convention-based annotation attribute overrides is \
297-
deprecated and will be removed in Spring Framework 6.1. Please \
298-
annotate the '%s' attribute in @%s with an appropriate @AliasFor \
299-
declaration -- for example, @AliasFor(annotation = %s.class)."""
300-
.formatted(name, rootAnnotationTypeName, this.annotationType.getName()));
301-
}
291+
conventionMappedAttributes.add(name);
302292
mappings[i] = mapped;
303293
MirrorSet mirrors = getMirrorSets().getAssigned(i);
304294
if (mirrors != null) {
@@ -308,6 +298,16 @@ private void addConventionMappings() {
308298
}
309299
}
310300
}
301+
String rootAnnotationTypeName = this.root.annotationType.getName();
302+
// We want to avoid duplicate log warnings as much as possible, without full synchronization.
303+
if (conventionBasedOverrideCheckCache.add(rootAnnotationTypeName) &&
304+
!conventionMappedAttributes.isEmpty() && logger.isWarnEnabled()) {
305+
logger.warn("""
306+
Support for convention-based annotation attribute overrides is deprecated \
307+
and will be removed in Spring Framework 6.1. Please annotate the following \
308+
attributes in @%s with appropriate @AliasFor declarations: %s"""
309+
.formatted(rootAnnotationTypeName, conventionMappedAttributes));
310+
}
311311
}
312312

313313
/**

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2445,6 +2445,10 @@ static class MetaMetaAliasedTransactionalClass {
24452445
// Do NOT use @AliasFor here until Spring 6.1
24462446
// @AliasFor(annotation = ContextConfiguration.class)
24472447
String[] locations() default {};
2448+
2449+
// Do NOT use @AliasFor here until Spring 6.1
2450+
// @AliasFor(annotation = ContextConfiguration.class)
2451+
Class<?>[] classes() default {};
24482452
}
24492453

24502454
@ContextConfiguration(value = "duplicateDeclaration")

0 commit comments

Comments
 (0)