thinking-in-spring-boot-samples
thinking-in-spring-boot-samples copied to clipboard
7.3.4 Spring 注解属性别名与覆盖这一章节的疑惑
小马哥 @mercyblitz 你好,对于 Spring 注解属性覆盖与别名这一章节,个人觉得属性隐式覆盖例子使用 @Service
与 @Component
value 属性覆盖有点不合适。
测试过程中,发现隐式覆盖对于 value 属性不生效的,查看源码发现,其覆盖属性的排除了 value 属性。源码位置:
MergedAnnotationAttributesProcessor#postProcess
1613 行
// Implicit annotation attribute override based on convention
else if (!AnnotationUtils.VALUE.equals(attributeName) && attributes.containsKey(attributeName)) {
overrideAttribute(element, annotation, attributes, attributeName, attributeName);
}
Spring 版本 5.1.8-RELEASE
以下是我的测试例子。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Two
public @interface One {
String value() default "";
String name() default "one";
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Two {
String value() default "Two";
String name() default "two";
}
@One(value = "AnnotationAttributesTest",name = "AnnotationAttributesTest")
public class AnnotationAttributesTest {
public static void main(String[] args) {
AnnotatedElement annotatedElement = AnnotationAttributesTest.class;
AnnotationAttributes oneAttributes =
AnnotatedElementUtils.getMergedAnnotationAttributes(annotatedElement, One.class);
AnnotationAttributes twoAttributes =
AnnotatedElementUtils.getMergedAnnotationAttributes(annotatedElement, Two.class);
print(oneAttributes);
print(twoAttributes);
}
private static void print(AnnotationAttributes annotationAttributes) {
System.out.printf("注解 @%s 属性集合 : \n", annotationAttributes.annotationType().getName());
annotationAttributes.forEach((name, value) ->
System.out.printf("\t属性 %s : %s \n", name, value)
);
}
}
输出结果:
注解 @com.spring.learning.customizescanning.annotation.One 属性集合 :
属性 name : AnnotationAttributesTest
属性 value : AnnotationAttributesTest
注解 @com.spring.learning.customizescanning.annotation.Two 属性集合 :
属性 name : AnnotationAttributesTest
属性 value : Two
从测试例子可以看到,隐式覆盖确实对 value 属性不生效。
所以个人觉得书中隐式覆盖的例子,会导致误解,认为隐式覆盖不会导致高层次同名属性值被低层次属性值覆盖(高层次属性值等于低层次注解属性值)。
或者说还是我对这个理解错误了?
待我确认一下,再给出准确的答复
- 在spring 容器中@Component value可以隐式覆盖,在书中定义@TransactionalService("txManager") 覆盖了beanName=txManager 事务管理器 ;生成beanName org.springframework.beans.factory.support.BeanNameGenerator#generateBeanName,合并AnnotationAttribute的是这个方法: AnnotationReadingVisitorUtils#getMergedAnnotationAttributes '@'since 4.0.3, 且不能使用@AlisaFor 显示覆盖。’
- 普通的属性覆盖调用的是该方法,隐式覆盖时排除了value AnnotatedElementUtils#getMergedAnnotationAttributes '@'since 4.2
Q: Can @AliasFor be used with the value attributes for @Component and @Qualifier? The short answer is: no.
The value attributes in @Qualifier and in stereotype annotations (e.g., @Component, @Repository, @Controller, and any custom stereotype annotations) cannot be influenced by @AliasFor. The reason is that the special handling of these value attributes was in place years before @AliasFor was invented. Consequently, due to backward compatibility issues it is simply not possible to use @AliasFor with such value attributes.
相关 issue #61