Java “春天是怎样的?”;“神奇地”;知道使用哪种Bean类型吗?

Java “春天是怎样的?”;“神奇地”;知道使用哪种Bean类型吗?,java,spring,Java,Spring,使用Spring5时,我很困惑注释ConfigApplicationContext“神奇地”知道如何使用接口的正确实现,因为引用的是接口而不是实现类 插图 注意:已输入不相关的代码,如导入和不相关的行为 一个接口CleaningTool和两个实现类Broom和VacuumCleaner,在接口方法doCleanJob() 然后,我的AnnotationConfigApplicationContex使用我的类AppConfig,因此: @Configuration public class App

使用Spring5时,我很困惑
注释ConfigApplicationContext
“神奇地”知道如何使用接口的正确实现,因为引用的是接口而不是实现类

插图 注意:已输入不相关的代码,如导入和不相关的行为

一个接口
CleaningTool
和两个实现类
Broom
VacuumCleaner
,在接口方法
doCleanJob()

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

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

    @Bean
    public CleaningTool vacuum(){
        return new VacuumCleaner();
    }
}
最后,在我的
MainApp
类中,我调用了
AnnotationConfigApplicationContext
getBean()
方法,在这里我测试了这一令人费解的现象,起初我认为它不起作用:

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

        ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);

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

    }
}
控制台输出:
Zoom

即使我的
AppConfig
MainApp
中的引用类型都是
CleaningTool
,Spring还是知道如何找到与类
VacuumCleaner.class
匹配的Bean,从而使用了
VacuumCleaner
的行为


这个“魔法”是如何工作的?

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

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

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

然后,应用程序上下文“就绪”,并调用以下行:

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

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

回答得很好!澄清一下我的困惑:事实上,应用程序上下文(在本例中)中带Bean注释的方法返回的是
CleaningTool
接口,而不是一个具体的类-这可能是您可以解释的吗?非常感谢,实际上这并不重要,我们都喜欢“编程到接口而不是具体类型”,但在这种情况下,spring无论如何都会知道这些是bean。毕竟它调用了
@Configuration
的这些方法,并得到了真正的对象。。。
@Configuration
public class AppConfig {
    @Bean
    public CleaningTool broom(){
        return new Broom();
    }

    @Bean
    public CleaningTool vacuum(){
        return new VacuumCleaner();
    }
}
public class MainApp {
    public static void main(String[] args) {

        ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);

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

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