1. 概述
在本文中,我們将探索@Qualifier注釋可以幫助我們做什麼,它解決了哪些問題,以及如何使用它。
我們還将解釋它與@Primary注釋和名稱自動裝配的差別。
2. Autowire需要明确的Bean
@Autowired 注解是一種很好的方式,可以顯式地将依賴注入到Spring中。盡管它很有用,但在某些情況下,僅此注釋不足以讓Spring了解注入哪個bean。
預設情況下,Spring根據類型解析自動加載條目。
如果容器中有多個相同類型的bean可用,架構将抛出NoUniqueBeanDefinitionException,表示有多個bean可用于自動裝配。
讓我們想象這樣一種情況:在給定的執行個體中,存在兩個可能的候選者,可以讓Spring作為bean協作者注入:
@Component("fooFormatter")public class FooFormatter implements Formatter { public String format() { return "foo"; }} @Component("barFormatter")public class BarFormatter implements Formatter { public String format() { return "bar"; }} @Componentpublic class FooService { @Autowired private Formatter formatter;}
3. @Qualifier注解
通過使用@Qualifier注解,我們可以消除需要注入哪個bean的問題。
讓我們回顧之前的例子,看看我們是如何通過包含@Qualifier注解來指出我們想使用哪個bean來解決這個問題的:
public class FooService { @Autowired @Qualifier("fooFormatter") private Formatter formatter;}
通過将@Qualifier注釋與我們想要使用的特定實作的名稱(在本例中為Foo)一起包含,我們可以避免在Spring發現相同類型的多個bean時出現歧義。
我們需要考慮使用的限定符名稱是在@Component注釋中聲明的。
注意,我們也可以在實作類的Formatter上使用@Qualifier注釋,而不是在它們的@Component注釋中指定名稱,以獲得相同的效果:
@[email protected]("fooFormatter")public class FooFormatter implements Formatter { //...} @[email protected]("barFormatter")public class BarFormatter implements Formatter { //...}
4. @Qualifier和@Primary對比
還有另一個名為@Primary的注釋,我們可以使用它來決定在依賴項注入出現歧義時注入哪個bean。
當存在多個相同類型的bean時,該注釋定義首選項。除非另有訓示,否則将使用與@Primary注釋關聯的bean。
示例如下:
@Configurationpublic class Config { @Bean public Employee johnEmployee() { return new Employee("John"); } @Bean @Primary public Employee tonyEmployee() { return new Employee("Tony"); }}
在本例中,這兩個方法傳回相同的雇員類型。Spring将注入的bean就是tonyEmployee方法傳回的bean。這是因為它包含@Primary注釋。當我們想要指定預設情況下應該注入特定類型的哪個bean時,這個注釋非常有用。
如果我們在某個注入點需要另一個bean,我們需要特别指出它。我們可以通過@Qualifier注釋來做到這一點。例如,我們可以通過使用@Qualifier注釋來指定我們想要使用johnEmployee方法傳回的bean。
值得注意的是,如果@Qualifier和@Primary注釋同時存在,那麼@Qualifier注釋将具有優先級。基本上,@Primary定義了一個預設值,而@Qualifier是非常特定的。
讓我們看看使用@Primary注釋的另一種方式,這次使用的是初始示例:
@[email protected] class FooFormatter implements Formatter { //...} @Componentpublic class BarFormatter implements Formatter { //...}
在本例中,@Primary注釋被放在一個實作類中,将消除場景的歧義。
5. @Qualifier和 @Autowired按名稱注入對比
在自動裝配時選擇多個bean的另一種方法是使用要注入的字段的名稱。這是在沒有其他Spring提示的情況下的預設值。讓我們看一些基于我們最初的例子的代碼:
public class FooService { @Autowired private Formatter fooFormatter;}
在本例中,Spring将确定要注入的bean是FooFormatter bean,因為字段名與我們在@Component注釋中為該bean使用的值相比對。
6. 總結
我們已經描述了需要消除要注入哪些bean的歧義的場景。特别是,我們描述了@Qualifier注釋,并将其與其他确定需要使用哪些bean的類似方法進行了比較。