Skip to content

Commit a68f5b1

Browse files
committed
Deprecate convention-based annotation attribute overrides
Implicit convention-based annotation attribute overrides have been supported for a long time; however, Spring Framework 4.2 introduced support for explicit annotation attribute overrides via @AliasFor. Since explicit overrides are favorable to implicit overrides, and since the support for convention-based overrides increases the complexity of Spring's annotation search algorithms, this commit deprecates convention-based overrides and logs a WARNING whey the are encountered. For example, the following message is logged for a test that still uses convention-based overrides. A log message is generated for each such attribute in a given annotation but only once per application run. WARN Support for convention-based annotation attribute overrides is deprecated and will be removed in Spring Framework 6.1. Please annotate the 'basePackages' attribute in @org.springframework.context.annotation.ConfigurationClassPostProcessorTests$ComposedConfigurationWithAttributeOverrides with an appropriate @AliasFor declaration. Closes gh-28760
1 parent 81acbe7 commit a68f5b1

File tree

1 file changed

+30
-0
lines changed

1 file changed

+30
-0
lines changed

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

+30
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@
2828
import java.util.List;
2929
import java.util.Map;
3030
import java.util.Set;
31+
import java.util.concurrent.ConcurrentHashMap;
32+
33+
import org.apache.commons.logging.Log;
34+
import org.apache.commons.logging.LogFactory;
3135

3236
import org.springframework.core.annotation.AnnotationTypeMapping.MirrorSets.MirrorSet;
3337
import org.springframework.lang.Nullable;
@@ -46,6 +50,17 @@
4650
*/
4751
final class AnnotationTypeMapping {
4852

53+
private static final Log logger = LogFactory.getLog(AnnotationTypeMapping.class);
54+
55+
/**
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.
59+
* @since 6.0
60+
* @see #addConventionMappings()
61+
*/
62+
private static final Set<String> conventionBasedOverrideCheckCache = ConcurrentHashMap.newKeySet();
63+
4964
private static final MirrorSet[] EMPTY_MIRROR_SETS = new MirrorSet[0];
5065

5166

@@ -273,6 +288,21 @@ private void addConventionMappings() {
273288
String name = this.attributes.get(i).getName();
274289
int mapped = rootAttributes.indexOf(name);
275290
if (!MergedAnnotation.VALUE.equals(name) && mapped != -1 && !isExplicitAttributeOverride(name)) {
291+
String rootAnnotationTypeName = this.root.annotationType.getName();
292+
// We want to avoid duplicate log warnings as much as possible, without
293+
// fully synchronizing on the cache.
294+
String cacheKey = rootAnnotationTypeName + "." + name;
295+
if (!conventionBasedOverrideCheckCache.contains(cacheKey)) {
296+
conventionBasedOverrideCheckCache.add(cacheKey);
297+
if (logger.isWarnEnabled()) {
298+
logger.warn("""
299+
Support for convention-based annotation attribute overrides is \
300+
deprecated and will be removed in Spring Framework 6.1. Please \
301+
annotate the '%s' attribute in @%s with an appropriate @AliasFor \
302+
declaration."""
303+
.formatted(name, rootAnnotationTypeName));
304+
}
305+
}
276306
mappings[i] = mapped;
277307
MirrorSet mirrors = getMirrorSets().getAssigned(i);
278308
if (mirrors != null) {

0 commit comments

Comments
 (0)