Spring 註解 @Qualifier 詳細解析

1. 概述

今天帶你瞭解一下 Spring 框架中的 @Qualifier 註解,它解決了哪些問題,以及如何使用它。咱們還將瞭解它與 @Primary 註解的不一樣之處。更多的技術解析請訪問 felord.cnjava

2. 痛點

使用 @Autowired 註解是 Spring 依賴注入的絕好方法。可是有些場景下僅僅靠這個註解不足以讓Spring知道到底要注入哪一個 bean。 默認狀況下,@Autowired 按類型裝配 Spring Bean。 若是容器中有多個相同類型的 bean,則框架將拋出 NoUniqueBeanDefinitionException, 以提示有多個知足條件的 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";
        }
    }

    @Component
    public class FooService {
        @Autowired
        private Formatter formatter;
        
        //todo 
    }
複製代碼

若是咱們嘗試將 FooService 加載到咱們的上下文中,Spring 框架將拋出 NoUniqueBeanDefinitionException。這是由於 Spring 不知道要注入哪一個 bean。爲了不這個問題,有幾種解決方案。那麼咱們本文要講解的 @Qualifier 註解就是其中之一。跟着小胖哥的節奏往下走。spa

3. @Qualifier

經過使用 @Qualifier 註解,咱們能夠消除須要注入哪一個 bean 的問題。讓咱們從新回顧一下前面的例子,看看咱們如何經過包含 @Qualifier 註釋來指出咱們想要使用哪一個 bean 來解決問題:code

@Component
    public class FooService {
        @Autowired
        @Qualifier("fooFormatter")
        private Formatter formatter;
        
        //todo 
    }
複製代碼

經過將 @Qualifier 註解與咱們想要使用的特定 Spring bean 的名稱一塊兒進行裝配,Spring 框架就能從多個相同類型並知足裝配要求的 bean 中找到咱們想要的,避免讓Spring腦裂。咱們須要作的是@Component或者@Bean註解中聲明的value屬性以肯定名稱。 其實咱們也能夠在 Formatter 實現類上使用 @Qualifier 註釋,而不是在 @Component 或者 @Bean 中指定名稱,也能達到相同的效果:orm

@Component
     @Qualifier("fooFormatter")
     public class FooFormatter implements Formatter {
         public String format() {
             return "foo";
         }
     }
 
     @Component
     @Qualifier("barFormatter")
     public class BarFormatter implements Formatter {
         public String format() {
             return "bar";
         }
     }
複製代碼

4. @Qualifier VS @Primary

還有另外一個名爲 @Primary 的註解,咱們也能夠用來發生依賴注入的歧義時決定要注入哪一個 bean。當存在多個相同類型的 bean 時,此註解定義了首選項。除非另有說明,不然將使用與 @Primary 註釋關聯的 bean 。 咱們來看一個例子:cdn

@Bean
    public Employee tomEmployee() {
        return new Employee("Tom");
    }

    @Bean
    @Primary
    public Employee johnEmployee() {
        return new Employee("john");
    }
複製代碼

在此示例中,兩個方法都返回相同的 Employee類型。Spring 將注入的 bean 是方法 johnEmployee 返回的 bean。這是由於它包含 @Primary 註解。當咱們想要指定默認狀況下應該注入特定類型的 bean 時,此註解頗有用。 若是咱們在某個注入點須要另外一個 bean,咱們須要專門指出它。咱們能夠經過 @Qualifier 註解來作到這一點。例如,咱們能夠經過使用 @Qualifier 註釋來指定咱們想要使用 tomEmployee 方法返回的 bean 。 值得注意的是,若是 @Qualifier@Primary 註釋都存在,那麼 @Qualifier 註釋將具備優先權。基本上,@Primary 是定義了默認值,而 @Qualifier 則很是具體。 固然@Component 也可使用@Primary 註解,此次使用的仍是上面3的示例:blog

@Component
     @Primary
     public class FooFormatter implements Formatter {
         public String format() {
             return "foo";
         }
     }
 
     @Component
     public class BarFormatter implements Formatter {
         public String format() {
             return "bar";
         }
     }
複製代碼

在這種狀況下,@Primary 註解指定了默認注入的是 FooFormatter,消除了場景中的注入歧義。隊列

5. 經過名稱來自動注入

在使用 @Autowired 進行自動裝配時,若是 Spring 沒有其餘提示,將會按照須要注入的變量名稱來尋找合適的 bean。也能夠解決依賴注入歧義的問題。讓咱們看一些基於咱們最初的例子的代碼:開發

@Component
    public class FooService {
        @Autowired
        private Formatter fooFormatter;
        
        //todo 
    }
複製代碼

在這種狀況下,Spring 將肯定要注入的 beanFooFormatter,由於字段名稱與咱們在該 bean@Component或者 @Bean 註解中使用的值(默認 @Bean 使用方法名)相匹配。get

6. 總結

經過對 @Qualifier 的探討,咱們知道該註解是用來消除依賴注入衝突的。這種在平常開發,好比 Rabbtimq 的隊列聲明中很常見。小胖哥也經過該註解和其餘上述註解的組合使用和對比中展現了一些經常使用的用法。這將有助於你對 Spring 的依賴注入機制的瞭解。

關注公衆號:Felordcn獲取更多資訊

我的博客:https://felord.cn

相關文章
相關標籤/搜索