[英]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.