有时接口是用@Component注释注释的。然后我明显的推理是实现这种接口的类也将被视为组件。但如果我是对的,情况并非如此。
那么在接口上@Component注解的目的是什么。
使用@Component
注释接口对于Spring类很常见,尤其是对于一些Spring原型注释:
package org.springframework.stereotype;
...
@Component
public @interface Service {...}
或:
package org.springframework.boot.test.context;
...
@Component
public @interface TestComponent {...}
@Component
未声明为继承的注释:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Component {...}
但是无论如何,在加载上下文期间,Spring通过考虑候选类中声明的注释的层次结构来发现bean。
在从底层源加载bean定义的org. springframe.boot.BeanDefitionLoader
类(包含在Spring Boot依赖项中)中,您可以看到org.springframe.core.annotation.AnnotationUtils.findAnnotion()
的示例,Spring使用它来检索注释的整个层次结构中的注释:
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原型。
事实并非如此,不需要在接口上添加@组件,因为它不是bean,因为我们无法为其创建引用。主要部分实际上是@autowed,您可以在其中注入依赖项。例如
公共接口SortAlog();公共类BubbleSortAlgo();
不,我们遵循动态绑定并创建接口对象,但实现是在运行时。
所以@autowed是一个将在内部创建对象的组件,我们有@组件用于bubbleSortAlgo和注入的唯一候选者,所以它将从那里获得引用。
我希望我能在这里说明一点。