【问题标题】:Interfaces are annotated with @Component annotation in spring IoC/DI. What could be the reason?接口在 Spring IoC/DI 中使用 @Component 注释进行注释。可能是什么原因?
【发布时间】:2018-03-12 03:55:03
【问题描述】:

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

那么接口上@Component注解的作用是什么。

【问题讨论】:

  • “但如果我是对的,情况并非如此。” - 你为什么这么认为?
  • 无论如何我都测试过。即 Spring 无法检测和自动装配实现此类接口的类。我还必须明确地在类上添加 @Component 注释。
  • "有时接口使用@Component 注解进行注解。"能举个具体的例子吗?
  • 我在我的项目代码中看到了它。我对开源项目了解不多……所以无法有效地指出。我的想法是接口上的@Component 注释没有增加任何价值。因此,我看到的任何此类注释都可能是不必要的。只是有兴趣在 SoF 上讨论相同的内容。您的明确问题让我认为不需要在接口上进行此类注释?对吗?
  • ... 但是如果编译器可以抛出错误或至少警告这样的注释,因为它们没有添加任何值,它会更清楚吗?由于编译器没有做这样的事情,但我应该仔细检查一下,看看我没有遗漏任何重要的事情。

标签: java spring dependency-injection inversion-of-control spring-ioc


【解决方案1】:

使用 @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.springframework.boot.BeanDefinitionLoader类(包含在Spring Boot依赖项中)中,您可以看到一个示例 org.springframework.core.annotation.AnnotationUtils.findAnnotation() 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 构造型。

【讨论】:

  • @samshers,为什么这没有被标记为接受的答案?
【解决方案2】:

情况并非如此,不需要在接口上添加@component,因为它不是 bean,因为我们无法为它创建引用。 主要部分实际上是@autowired,您在其中注入依赖项。 例如

公共接口 SortAlog(); 公共类 BubbleSortAlgo();

不,我们正在遵循动态绑定并创建接口对象,但实现是在运行时。

所以@autowired 是在内部创建对象的对象,我们有用于bubbleSortAlgo 的@component 和唯一的注入候选对象,因此它将从那里获得引用。

我希望我能在这里提出一个观点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-18
    • 2013-01-04
    • 2016-12-30
    • 2018-08-05
    • 1970-01-01
    • 1970-01-01
    • 2020-09-10
    相关资源
    最近更新 更多