thinking-in-spring-boot-samples icon indicating copy to clipboard operation
thinking-in-spring-boot-samples copied to clipboard

7.3.4 Spring 注解属性别名与覆盖这一章节的疑惑

Open 9526xu opened this issue 5 years ago • 3 comments

小马哥 @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 属性不生效。

所以个人觉得书中隐式覆盖的例子,会导致误解,认为隐式覆盖不会导致高层次同名属性值被低层次属性值覆盖(高层次属性值等于低层次注解属性值)。

或者说还是我对这个理解错误了?

9526xu avatar Jul 09 '19 04:07 9526xu

待我确认一下,再给出准确的答复

mercyblitz avatar Jul 24 '19 15:07 mercyblitz

  1. 在spring 容器中@Component value可以隐式覆盖,在书中定义@TransactionalService("txManager") 覆盖了beanName=txManager 事务管理器 ;生成beanName org.springframework.beans.factory.support.BeanNameGenerator#generateBeanName,合并AnnotationAttribute的是这个方法: AnnotationReadingVisitorUtils#getMergedAnnotationAttributes '@'since 4.0.3, 且不能使用@AlisaFor 显示覆盖。’
  1. 普通的属性覆盖调用的是该方法,隐式覆盖时排除了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.

scyslz avatar Aug 26 '19 16:08 scyslz

相关 issue #61

mercyblitz avatar Dec 24 '19 14:12 mercyblitz