接口在Spring IoC / DI中使用@Component注释进行注释。可能是什么原因? [英] Interfaces are annotated with @Component annotation in spring IoC/DI. What could be the reason?
问题描述
有时,接口使用@Component注释进行注释。然后我明显的推理是,实现这种接口的类也将被视为组件。但如果我是对的,事实并非如此。
Some times interfaces are annotated with @Component annotation. Then my obvious reasoning was that classes that implement such interface will be treated as components as well. But if I am right that is not the case.
那么接口上@Component注释的目的是什么。
So what is the purpose of @Component annotation on interfaces.
推荐答案
使用 @Component
注释接口对于Spring类很常见,特别是对于一些Spring构造型注释:
Annotating an interface with @Component
is common for Spring classes, particularly for some Spring stereotype annotations :
package org.springframework.stereotype;
...
@Component
public @interface Service {...}
或:
package org.springframework.boot.test.context;
...
@Component
public @interface TestComponent {...}
@Component
未声明为继承的注释:
@Component
is not declared as an inherited annotation :
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Component {...}
但无论如何,在加载上下文期间,Spring会通过考虑候选类中声明的注释的层次结构来发现bean。
But whatever, during loading of the context, Spring discovers beans by considering the hierarchy of the annotation declared in the candidate class.
在 org.springframework.boot.BeanDefinitionLoader
类中(包含在Spring Boot依赖项中)从底层源加载bean定义,你可以看到一个
org.springframework.core.annotation.AnnotationUtils.findAnnotation()
的例子,Spring用它来检索注释的整个层次结构中的注释:
In the org.springframework.boot.BeanDefinitionLoader
class (included in the Spring Boot dependency) that loads bean definitions from underlying sources, you can see an example of
org.springframework.core.annotation.AnnotationUtils.findAnnotation()
that Spring uses to retrieve annotations in the whole hierarchy of the annotation:
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会考虑用<$ c $注释的候选类c> @Service 作为实例化的bean。
Concretely, it means as the @Service
annotation is itself annotated with @Component
, Spring will consider a candidate class annotated with @Service
as a bean to instantiate.
所以,你的猜测是正确的:
So, your guesswork is right :
实现此类接口的类将被视为
well的组件。
Classes that implement such interface will be treated as components as well.
但这仅适用于Java注释的接口(例如 @Service
),而不适用于普通接口。
But this works only for interfaces (such as @Service
) that are Java annotations and not for plain interfaces.
对于Spring类,这种做法很有意义(例如丰富实际的构造型)但对于你自己的bean,使用 @Component
对于接口而不是实现将无法工作,并将带来更多的缺点而不是优势:
For Spring classes, this way of doing makes sense (enriching actual stereotype for example) but for your own beans, using @Component
for the interface rather than the implementation will not work and would bring more drawbacks than advantages :
-
它以同样的方式失败上面的接口的目的所有的合同。它将它耦合到Spring,它假设您将始终只有一个类的实现。
在这种情况下,为什么要使用界面?
it defeats in a same way the purpose of an interface that is above all a contract. It couples it to Spring and it supposes that you will always have a single implementation of the class.
In this case, why using an interface ?
它会在两个位置分散类的读取,而界面不需要任何春天刻板印象。
it scatters the reading of the class at two places while the interface doesn't need to have any Spring stereotype.
这篇关于接口在Spring IoC / DI中使用@Component注释进行注释。可能是什么原因?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!