接口在Spring IoC / DI中使用@Component注释进行注释。 可能是什么原因?

有时,接口使用@Component注释进行注释。 然后我明显的推理是,实现这种接口的类也将被视为组件。 但如果我是对的,事实并非如此。

那么接口上@Component注释的目的是什么呢?

使用@Component注释接口对于Spring类很常见,特别是对于一些Spring构造型注释:

 package org.springframework.stereotype; ... @Component public @interface Service {...} 

要么 :

 package org.springframework.boot.test.context; ... @Component public @interface TestComponent {...} 

@Component未声明为inheritance的注释:

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

但无论如何,在加载上下文期间,Spring通过考虑候选类中声明的注释的层次结构来发现bean。

在从底层源加载bean定义的org.springframework.boot.BeanDefinitionLoader类(包含在Spring Boot依赖项中)中,您可以看到Spring用于检索的org.springframework.core.annotation.AnnotationUtils.findAnnotation()的示例注释的整个层次结构中的注释:

 class BeanDefinitionLoader { ... private boolean isComponent(Class type) { // This has to be a bit of a guess. The only way to be sure that this type is // eligible is to make a bean definition out of it and try to instantiate it. if (AnnotationUtils.findAnnotation(type, Component.class) != null) { return true; } // Nested anonymous classes are not eligible for registration, nor are groovy // closures if (type.getName().matches(".*\\$_.*closure.*") || type.isAnonymousClass() || type.getConstructors() == null || type.getConstructors().length == 0) { return false; } return true; } ... } 

具体来说,这意味着@Service注释本身用@Component注释,Spring会将使用@Service注释的候选类视为要实例化的bean。

所以,你的猜测是正确的:

实现此类接口的类也将被视为组件。

但这仅适用于Java注释的接口(例如@Service ),而不适用于普通接口

对于Spring类,这种做法很有意义(例如丰富实际的构造型)但是对于你自己的bean,使用@Component作为接口而不是实现将不起作用并且会带来更多的缺点而不是优点:

  • 它以同样的方式击败了一个最重要的合同接口的目的。 它将它耦合到Spring,它假设您将始终只有一个类的实现。
    在这种情况下,为什么要使用界面?

  • 它在两个地方分散了类的读取,而接口不需要任何Spring构造型。