使用 Spring 5,我很困惑 AnnotationConfigApplicationContext 到底如何“神奇地”知道使用我的接口(interface)的正确实现,因为引用是对接口(interface)而不是实现类。
插图
注意:省略了不相关的代码,例如导入和不相关的行为
一个接口(interface) CleaningTool
和两个实现类 Broom
和 VacuumCleaner
,以及接口(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
类中,我调用了 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();
}
}
控制台输出:缩放缩放缩放
尽管我的 AppConfig
和 MainApp
中的引用类型都是 CleaningTool
,Spring 却以某种方式知道寻找与该类匹配的 Bean VacuumCleaner.class
,使用 VacuumCleaner
的行为。
这个“魔法”是如何发挥作用的?
最佳答案
@Configuration
旨在提供定义 bean 的工具。
Spring 创建这些 bean(类的实例)并将它们存储在 ApplicationContext 中。
您可以将应用程序上下文视为一个映射,其中包含实际 bean 的 id/类到相应单例的实际实例之间的映射。
因此,当 spring 启动时,它会创建 Broom
和 VacuumCleaner
并将这两个 bean 放入应用程序上下文中。
然后应用程序上下文已“准备就绪”,您可以调用以下行:
CleaningTool vacuum = ctx.getBean(VacuumCleaner.class);
请注意,您不需要接口(interface)CleaningTool
,而是需要具体类VacuumCleaner
。在这种情况下,spring 会转到其内部映射并仅通过具体类检索值(实际对象)。这里没有魔法:)
关于java - Spring "magically"如何知道要使用哪种 Bean 类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62514783/