问题 无法让@Component在Spring中继承?


在我的项目中,有一个所有客户端类都扩展的公共基类。这有一个@Autowired字段,需要由Hibernate注入。这些都在另一个具有@Autowired基类集合的类中组合在一起。

为了减少客户端代码的样板,我试图让@Component继承。 @Component默认情况下不这样做(显然 过去曾经如此),我创建了这个变通方法注释

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Component
@Inherited
public @interface InheritedComponent {
}

...并用它注释基类。它不漂亮,但我希望它会起作用。不幸的是它没有,这真让我感到困惑,因为@Inherited应该让它发挥作用

还有其他方法可以继承@Component吗?或者我只是要说任何扩展基类的类都需要这个样板?


7593
2017-08-02 12:48


起源



答案:


问题是, Component 注释类型本身需要标记 @Inherited

你的 @InheritedComponent 注释类型由扩展标记为的超类的任何类正确继承 @InheritedComponent  - 但它没有继承 @Component。这是因为你有 @Component 在...上 注解,而不是父类型。

一个例子:

public class InheritedAnnotationTest {

    @InheritedComponent
    public static class BaseComponent {
    }

    public static class SubClass extends BaseComponent {
    }

    public static void main(String[] args) {
        SubClass s = new SubClass();

        for (Annotation a : s.getClass().getAnnotations()) {
            System.out.printf("%s has annotation %s\n", s.getClass(), a);
        }
    }
}

输出:

class brown.annotations.InheritedAnnotationTest $ SubClass有注释@ brown.annotations.InheritedComponent()

换句话说,当解析类具有的注释时,注释的注释不会被解析 - 它们不适用于类,只适用于注释(如果有意义)。


9
2017-08-02 13:36



嗯,我以为我能做到这一点,因为像 @Repository 用...注释 @Component。猜猜我只需要发出一个大警告说:“如果你扩展这门课程,你就可以了 必须 用它注释 @Component“样板。 - TheLQ
我相信这些是可行的,因为扫描Component注释的Spring类具有检查注释注释的特殊逻辑 -​​ 看看ClassPathScanningCandidateComponentProvider和AnnotationTypeFilter。可能还有一种方法可以使Component注释注释起作用 - matt b


答案:


问题是, Component 注释类型本身需要标记 @Inherited

你的 @InheritedComponent 注释类型由扩展标记为的超类的任何类正确继承 @InheritedComponent  - 但它没有继承 @Component。这是因为你有 @Component 在...上 注解,而不是父类型。

一个例子:

public class InheritedAnnotationTest {

    @InheritedComponent
    public static class BaseComponent {
    }

    public static class SubClass extends BaseComponent {
    }

    public static void main(String[] args) {
        SubClass s = new SubClass();

        for (Annotation a : s.getClass().getAnnotations()) {
            System.out.printf("%s has annotation %s\n", s.getClass(), a);
        }
    }
}

输出:

class brown.annotations.InheritedAnnotationTest $ SubClass有注释@ brown.annotations.InheritedComponent()

换句话说,当解析类具有的注释时,注释的注释不会被解析 - 它们不适用于类,只适用于注释(如果有意义)。


9
2017-08-02 13:36



嗯,我以为我能做到这一点,因为像 @Repository 用...注释 @Component。猜猜我只需要发出一个大警告说:“如果你扩展这门课程,你就可以了 必须 用它注释 @Component“样板。 - TheLQ
我相信这些是可行的,因为扫描Component注释的Spring类具有检查注释注释的特殊逻辑 -​​ 看看ClassPathScanningCandidateComponentProvider和AnnotationTypeFilter。可能还有一种方法可以使Component注释注释起作用 - matt b


我通过创建自己的注释(heritable)然后自定义类路径扫描来处理这个问题:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Component 
@Inherited
public @interface BusinessService {
}

Spring配置看起来像这样:

<context:component-scan base-package="io.bar">
        <context:include-filter type="annotation"
            expression="io.bar.core.annotations.BusinessService" />
    </context:component-scan>

Spring doc 5.10.3使用过滤器自定义扫描


7
2017-10-02 15:15