|
1 | 1 | /*
|
2 |
| - * Copyright 2002-2023 the original author or authors. |
| 2 | + * Copyright 2002-2025 the original author or authors. |
3 | 3 | *
|
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
5 | 5 | * you may not use this file except in compliance with the License.
|
|
17 | 17 | package org.springframework.context.annotation;
|
18 | 18 |
|
19 | 19 | import java.lang.annotation.Annotation;
|
| 20 | +import java.lang.reflect.Method; |
20 | 21 | import java.util.Collections;
|
21 | 22 | import java.util.HashSet;
|
22 | 23 | import java.util.LinkedHashSet;
|
|
33 | 34 | import org.springframework.beans.factory.config.BeanDefinition;
|
34 | 35 | import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
35 | 36 | import org.springframework.beans.factory.support.BeanNameGenerator;
|
| 37 | +import org.springframework.core.annotation.AliasFor; |
36 | 38 | import org.springframework.core.annotation.AnnotationAttributes;
|
37 | 39 | import org.springframework.core.annotation.MergedAnnotation;
|
38 | 40 | import org.springframework.core.annotation.MergedAnnotation.Adapt;
|
|
41 | 43 | import org.springframework.lang.Nullable;
|
42 | 44 | import org.springframework.util.Assert;
|
43 | 45 | import org.springframework.util.ClassUtils;
|
| 46 | +import org.springframework.util.ReflectionUtils; |
44 | 47 | import org.springframework.util.StringUtils;
|
45 | 48 |
|
46 | 49 | /**
|
@@ -147,16 +150,26 @@ protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotat
|
147 | 150 | Set<String> metaAnnotationTypes = this.metaAnnotationTypesCache.computeIfAbsent(annotationType,
|
148 | 151 | key -> getMetaAnnotationTypes(mergedAnnotation));
|
149 | 152 | if (isStereotypeWithNameValue(annotationType, metaAnnotationTypes, attributes)) {
|
150 |
| - Object value = attributes.get("value"); |
| 153 | + Object value = attributes.get(MergedAnnotation.VALUE); |
151 | 154 | if (value instanceof String currentName && !currentName.isBlank()) {
|
152 | 155 | if (conventionBasedStereotypeCheckCache.add(annotationType) &&
|
153 | 156 | metaAnnotationTypes.contains(COMPONENT_ANNOTATION_CLASSNAME) && logger.isWarnEnabled()) {
|
154 |
| - logger.warn(""" |
155 |
| - Support for convention-based stereotype names is deprecated and will \ |
156 |
| - be removed in a future version of the framework. Please annotate the \ |
157 |
| - 'value' attribute in @%s with @AliasFor(annotation=Component.class) \ |
158 |
| - to declare an explicit alias for @Component's 'value' attribute.""" |
159 |
| - .formatted(annotationType)); |
| 157 | + if (hasExplicitlyAliasedValueAttribute(mergedAnnotation.getType())) { |
| 158 | + logger.warn(""" |
| 159 | + Although the 'value' attribute in @%s declares @AliasFor for an attribute \ |
| 160 | + other than @Component's 'value' attribute, the value is still used as the \ |
| 161 | + @Component name based on convention. As of Spring Framework 7.0, such a \ |
| 162 | + 'value' attribute will no longer be used as the @Component name.""" |
| 163 | + .formatted(annotationType)); |
| 164 | + } |
| 165 | + else { |
| 166 | + logger.warn(""" |
| 167 | + Support for convention-based @Component names is deprecated and will \ |
| 168 | + be removed in a future version of the framework. Please annotate the \ |
| 169 | + 'value' attribute in @%s with @AliasFor(annotation=Component.class) \ |
| 170 | + to declare an explicit alias for @Component's 'value' attribute.""" |
| 171 | + .formatted(annotationType)); |
| 172 | + } |
160 | 173 | }
|
161 | 174 | if (beanName != null && !currentName.equals(beanName)) {
|
162 | 175 | throw new IllegalStateException("Stereotype annotations suggest inconsistent " +
|
@@ -224,7 +237,7 @@ protected boolean isStereotypeWithNameValue(String annotationType,
|
224 | 237 | annotationType.equals("jakarta.inject.Named") ||
|
225 | 238 | annotationType.equals("javax.inject.Named");
|
226 | 239 |
|
227 |
| - return (isStereotype && attributes.containsKey("value")); |
| 240 | + return (isStereotype && attributes.containsKey(MergedAnnotation.VALUE)); |
228 | 241 | }
|
229 | 242 |
|
230 | 243 | /**
|
@@ -255,4 +268,14 @@ protected String buildDefaultBeanName(BeanDefinition definition) {
|
255 | 268 | return StringUtils.uncapitalizeAsProperty(shortClassName);
|
256 | 269 | }
|
257 | 270 |
|
| 271 | + /** |
| 272 | + * Determine if the supplied annotation type declares a {@code value()} attribute |
| 273 | + * with an explicit alias configured via {@link AliasFor @AliasFor}. |
| 274 | + * @since 6.2.3 |
| 275 | + */ |
| 276 | + private static boolean hasExplicitlyAliasedValueAttribute(Class<? extends Annotation> annotationType) { |
| 277 | + Method valueAttribute = ReflectionUtils.findMethod(annotationType, MergedAnnotation.VALUE); |
| 278 | + return (valueAttribute != null && valueAttribute.isAnnotationPresent(AliasFor.class)); |
| 279 | + } |
| 280 | + |
258 | 281 | }
|
0 commit comments