提问者:小点点

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


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

那么在接口上@Component注解的目的是什么。


共2个答案

匿名用户

使用@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和注入的唯一候选者,所以它将从那里获得引用。

    我希望我能在这里说明一点。