sam*_*ers 9 java spring dependency-injection inversion-of-control spring-ioc
有时接口会使用@Component 注解进行注解。那么我的明显推理是实现此类接口的类也将被视为组件。但如果我是对的,情况就不是这样了。
那么接口上@Component注解的目的是什么呢?
使用注释接口@Component对于 Spring 类来说很常见,特别是对于一些 Spring 构造型注释:
package org.springframework.stereotype;
...
@Component
public @interface Service {...}
Run Code Online (Sandbox Code Playgroud)
或者 :
package org.springframework.boot.test.context;
...
@Component
public @interface TestComponent {...}
Run Code Online (Sandbox Code Playgroud)
@Component未声明为继承注释:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Component {...}
Run Code Online (Sandbox Code Playgroud)
但无论如何,在加载上下文期间,Spring 通过考虑候选类中声明的注释的层次结构来发现 bean。
在从底层源加载 bean 定义的类(包含在 Spring Boot 依赖项中)中,您可以看到Spring 用于在整个注释层次结构中检索注释org.springframework.boot.BeanDefinitionLoader的示例
: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;
}
...
}
Run Code Online (Sandbox Code Playgroud)
具体来说,这意味着当@Service注释本身被注释为 时@Component,Spring 会将注释为 的候选类视为@Service要实例化的 bean。
所以,你的猜测是正确的:
实现此类接口的类也将被视为组件。
但这仅适用于@Service作为 Java 注释的接口(例如),而不适用于普通接口。
对于 Spring 类,这种做法是有意义的(例如,丰富实际的构造型),但对于您自己的 bean,使用@Component接口而不是实现将不起作用,并且会带来更多的缺点而不是优点:
它以同样的方式破坏了接口首先是契约的目的。它将它与 Spring 结合起来,并假设您将始终拥有该类的单个实现。
既然如此,为什么要使用接口呢?
它将类的读取分散在两个地方,而接口不需要有任何 Spring 构造型。