java - Spring "magically"如何知道要使用哪种 Bean 类型?

标签 java spring

使用 Spring 5,我很困惑 AnnotationConfigApplicationContext 到底如何“神奇地”知道使用我的接口(interface)的正确实现,因为引用是对接口(interface)而不是实现类。

插图

注意:省略了不相关的代码,例如导入和不相关的行为

一个接口(interface) CleaningTool 和两个实现类 BroomVacuumCleaner,以及接口(interface)方法 doCleanJob() 的变体>

public interface CleaningTool {
    void doCleanJob();
}
public class Broom implements CleaningTool {
    @Override
    public void doCleanJob() {
        System.out.println("Sweep sweep sweep");
    }
}
public class VacuumCleaner implements CleaningTool {
    @Override
    public void doCleanJob() {
        System.out.println("Zoom zoom zoom");
    }
}

然后,我的 AnnotationConfigApplicationContex 使用我的类 AppConfig:

@Configuration
public class AppConfig {
    @Bean
    public CleaningTool broom(){
        return new Broom();
    }

    @Bean
    public CleaningTool vacuum(){
        return new VacuumCleaner();
    }
}

最后,在我的 MainApp 类中,我调用了 AnnotationConfigApplicationContextgetBean() 方法,这是我测试这种令人费解的现象的地方起初我预计不会起作用:

public class MainApp {
    public static void main(String[] args) {

        ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);

        CleaningTool vacuum = ctx.getBean(VacuumCleaner.class);
        vacuum.doCleanJob();

    }
}

控制台输出:缩放缩放缩放

尽管我的 AppConfigMainApp 中的引用类型都是 CleaningTool,Spring 却以某种方式知道寻找与该类匹配的 Bean VacuumCleaner.class,使用 VacuumCleaner 的行为。

这个“魔法”是如何发挥作用的?

最佳答案

@Configuration 旨在提供定义 bean 的工具。 Spring 创建这些 bean(类的实例)并将它们存储在 ApplicationContext 中。

您可以将应用程序上下文视为一个映射,其中包含实际 bean 的 id/类到相应单例的实际实例之间的映射。

因此,当 spring 启动时,它会创建 BroomVacuumCleaner 并将这两个 bean 放入应用程序上下文中。

然后应用程序上下文已“准备就绪”,您可以调用以下行:

CleaningTool vacuum = ctx.getBean(VacuumCleaner.class);

请注意,您不需要接口(interface)CleaningTool,而是需要具体类VacuumCleaner。在这种情况下,spring 会转到其内部映射并仅通过具体类检索值(实际对象)。这里没有魔法:)

关于java - Spring "magically"如何知道要使用哪种 Bean 类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62514783/

相关文章:

java - 不使用AOP拦截带注释的方法调用

java - volatile 关键字对于同步 java block 有什么重要性?

mysql - Spring Boot、Spring Security、MySQL - CustomUserDetailsS​​ervice 始终导致错误 "Invalid Username or Password"

java - 如何 JUnit 测试 Wicket 页面

java - 如何将@Before/@BeforeClass 与@Autowired 字段一起使用

java.lang.IllegalStateException : Input resource must exist (reader is in 'strict' mode): class path resource

java - 从未确定的子类到父类(super class)的转换

java - 线程 "main"java.lang.UnsatisfiedLinkError : A dynamic link library (DLL) initialization routine failed 中的异常

java - 由于缺少文件而无法编译

java - 如何查找mongodb中嵌入嵌套数组的长度?