Spring註解@Qualifier的詳細用法你知道幾種
環境:springboot2.3.10
一般使用在項目中使用@Qualifier來限定註入的Bean。
由於項目中我習慣用@Resource註解,所以這裡先對@Autowired和@Resource進行個簡單的說明。
@Autowired和@Resource區別
相同點:
@Autowired與@Resource都可以用來裝配Bean。都可以寫在字段上,或寫在setter方法上。
區別:
1、@Autowired(Spring註解)
默認按類型裝配,默認情況下必須要求依賴對象必須存在(不存在會報錯),可以通過required=false屬性設置非必須 ,如果我們想使用名稱裝配可以結合@Qualifier註解進行使用,示例如下:
@Autowired(required = false) private Date date ; @Autowired @Qualifier("birth") private Date birthday ;
當系統中存在多個相同類型的Bean時,如果不使用@Qualifier程序啟動是會報錯
@Bean public Date d1() { return new Date() ; } @Bean public Date d2() { return new Date() ; } @Autowired private Date date ;
2、@Resoure(JavaEE註解)
默認按照名稱進行裝配,可以通過name屬性指定名稱,如果沒有指定name屬性,當註解寫在字段上時,默認取字段名進行查找註入,如果寫在setter方法上默認取屬性名進行裝配。當找不到與名稱匹配的bean時才按照類型進行裝配。但是需要註意的是,如果name屬性一旦指定,就隻會按照名稱進行裝配。示例:
還是上面的例子
@Resource private Date date
啟動後會報錯:
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type ‘java.util.Date’ available: expected single matching bean but found 2: d1,d2
因為我們沒有以date為名稱的bean,所以會按照類型進行註入,但是類型又有兩個Date的Bean。將date改為d1或者d2或者指明name屬性。
@Resource("d1") private Date date
@Autowired和@Resource就介紹到這裡瞭
常規用法限定註入類
通過上面的示例我們已經瞭解瞭@Qualifier的主用
@Autowired @Qualifier("d1") private Date date ;
用來限定註入的Bean的名稱。這種用法也是很好的理解,接下來我們介紹通過@Qualifier來篩選限定註入對象。
@Qualifier篩選註入對象
直接使用@Qualifier限定
@Qualifier @Bean public Date d1() { return new Date() ; } @Bean public Date d2() { return new Date() ; } @Resource private List<Date> dates = Collections.emptyList() ;
打印dates集合:
集合中註入瞭2個Date Bean。
修改代碼:
@Resource @Qualifier private List<Date> dates = Collections.emptyList() ;
在屬性上加入@Qualifier註解
執行結果:
隻註入瞭一個Date Bean。
@Qualifier起到瞭一個篩選的作用隻有Bean上加有@Qualifier註解的Bean才會被收集註入。
自定義註解限定註入Bean
@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Qualifier public @interface FK { }
註意:該自定義註解上添加有@Qualifier註解。
@FK @Bean public Date d1() { return new Date() ; } @Bean public Date d2() { return new Date() ; } @Resource @FK private List<Date> dates = Collections.emptyList() ;
運行:
註入瞭一個Date Bean。
該使用示例在Spring Cloud中Ribbon是也有應用的。
在使用Ribbon做負載均衡時,在配置RestTemplate時會加入如下註解:
@LoadBalanced @Bean public RestTemplate restTemplate() { return new RestTemplate() ; } @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Qualifier public @interface LoadBalanced { }
在Ribbon的自動配置類中:
這裡指明瞭隻收集帶有@LoadBalanced註解的RestTemplate對象。然後給對應RestTemplate設置攔截器來實現直接通過服務名就能調用接口。接下來簡單介紹下RestTemplate怎麼實現負載均衡。
攔截器中就開始獲取服務名,然後調用createRequest方法來將serviceName換成真實的IP
ServiceRequestWrapper類
進入ServiceRequestWrapper類,該類重寫瞭HttpRequest對象的getURI方法
通過負載均衡重寫構造URI
這裡相關的Ribbon相關實現的負載均衡我們都省略瞭,這裡給出幾個核心的類:
LoadBalancerAutoConfiguration.java 負載均衡自動配置
RibbonClientConfiguration.java ribbon客戶端相關配置,比如:負載均衡的算法,服務列表的更新,ping健康檢查等。如果想自定義實現負載均衡算法可以實現IRule類。
完畢!!!
到此這篇關於Spring註解@Qualifier這種用法你知道嗎?的文章就介紹到這瞭,更多相關Spring註解@Qualifier內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- 深入分析@Resource和@Autowired註解區別
- springboot多數據源使用@Qualifier自動註入無效的解決
- Spring cloud alibaba之Ribbon負載均衡實現方案
- 淺談spring DI 依賴註入方式和區別
- SpringCloud筆記(Hoxton)Netflix之Ribbon負載均衡示例代碼