簡體   English   中英

即使在 spring 中使用限定符,也會調用 Autowire 構造函數兩次

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM