[英]Autowire constructor is called twice even using Qualifier in spring
我正在尝试使用 spring 中的限定符来学习自动装配,并且自动装配的 class 构造函数被调用了两次。 我有以下 class:
主应用:
public class MainApp {
public static void main(String[] args) {
// ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
ApplicationContext ctx =
new AnnotationConfigApplicationContext(HelloWorldConfig.class);
// TextEditor obj = (TextEditor) ctx.getBean("helloWorld");
TextEditor obj = (TextEditor)ctx.getBean(TextEditor.class);
obj.spellCheck();
}
拼写检查器:
public class SpellChecker {
public SpellChecker() {
System.out.println("Inside SpellChecker constructor.");
}
public void checkSpelling() {
System.out.println("Inside checkSpelling.");
}
文本编辑器
public class TextEditor {
@Qualifier("a")
@Autowired
private SpellChecker spellChecker;
public SpellChecker getSpellChecker( ) {
return spellChecker;
}
public void spellCheck() {
spellChecker.checkSpelling();
}
}
我有基于 java 的配置,它有多个具有相同类型的 bean,并且想要 select 一个带有限定符的 bean,但是 output 显示构造函数被调用了两次。
HelloWorldConfig
@Component
public class HelloWorldConfig {
@Bean
public HelloWorld helloWorld(){
return new HelloWorld();
}
@Bean
public TextEditor textEditor(){
return new TextEditor();
}
@Bean(name="a")
public SpellChecker spellChecker(){
return new SpellChecker();
}
@Bean(name="b")
public SpellChecker spellChecker1(){
return new SpellChecker();
}
}
OUTPUT:
Inside SpellChecker constructor.
Inside SpellChecker constructor.
Inside checkSpelling.
我期待一个 SpellChecker 构造函数调用,因为我使用 Qualifier("a") 来指定 bean,但是即使我使用 Qualifier 到 select 单个 bean,构造函数也会被调用两次。 为什么叫两次??
查看HelloWorldConfig
文件。 您已经声明了 2 个 SpellChecker 类型的 bean:
@Bean(name="a")
public SpellChecker spellChecker(){
return new SpellChecker();
}
@Bean(name="b")
public SpellChecker spellChecker1(){
return new SpellChecker();
}
这两个 bean 都是由 spring 创建的,尽管只有一个 bean 被注入到TextEditor
中。
在 spring 中,拥有多个相同类型的 bean 或实现相同接口的 bean 完全没问题(想想监听器 - 可能有很多) - 所以 spring 容器将在应用程序启动期间创建它们。
但是,如果您想将其中一个 bean 注入另一个 bean(例如您的情况下的TextEditor
), spring 将不知道要注入哪个 bean,这就是您添加“限定符”功能的原因。
另请注意,您错误地在配置 class 上放置了@Component
注释,而不是您应该使用@Configuration
注释来指定此 class 包含一系列 bean 定义(您确实使用@Bean
注释声明)。 尽管“配置”也是一个组件(由 spring 管理) - spring 仍然以与普通 bean 截然不同的方式对待它。
还有一个注意事项:虽然它与您的问题没有直接关系,但您似乎在您提供的代码片段中混合了 2 styles 配置: @Qualifier/@Autowired
的样式(这种方式已添加到 spring 2.5如果我没记错的话)和 java 配置的风格: @Configuration
class 和@Bean
-s 在里面。
您可以完全避免使用自动装配,并通过从 java 配置调用的构造函数注入依赖项,如下所示:
@Configuration
public class HelloWorldConfig {
@Bean
public HelloWorld helloWorld(){
return new HelloWorld();
}
@Bean
public TextEditor textEditor(@Qualifier("a") SpellChecker spellChecker){ // note the dependency here
return new TextEditor(spellChecker);
}
@Bean(name="a")
public SpellChecker spellChecker(){
return new SpellChecker();
}
@Bean(name="b")
public SpellChecker spellChecker1(){
return new SpellChecker();
}
}
// the TextEditor Class should have a constructor with one argument:
public class TextEditor {
private final SpellChecker spellChecker;
public TextEditor(SpellChecker spellChecker) {
this.spellChecker = spellChecker;
}
...
}
// or if you use lombok library:
@AllArgsConstructor
public class TextEditor {
private final SpellChecker spellChecker;
...
}
现在请注意,您的“业务类”甚至不知道 spring 所有“分辨率”(使用限定符和注入规则)都是在 spring 配置中完成的,无论如何这是一个特殊的 ZA2F2ED4F8EBC2CBB4C21A29DC4。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.