Spring如何正確注入集合類型
集合類型的自動注入是Spring提供的另外一個強(qiáng)大功能。我們在方便的使用依賴注入的特性時,必須要思考對象從哪里注入、怎么創(chuàng)建、為什么是注入這一個對象的。雖然編寫框架的目的是讓開發(fā)人員無需關(guān)心太多底層細(xì)節(jié),能專心業(yè)務(wù)邏輯的開發(fā),但是作為開發(fā)人員不能真的無腦去使用框架。
務(wù)必學(xué)會注入集合等高級用法,讓自己有所提升!
現(xiàn)在有一需求:存在多個用戶Bean,找出來存儲到一個List。
1 注入方式
1.1 收集方式
多個用戶Bean定義:
有了集合類型的自動注入后,即可收集零散的用戶Bean:
這樣即可完成集合類型注入:
但當(dāng)持續(xù)增加一些user時,可能就不喜歡用上述的注入集合類型了,而是這樣:
1.2 直接裝配方式
分開玩,大家應(yīng)該不會有啥問題,若兩種方式共存了,會咋樣?
運(yùn)行程序后發(fā)現(xiàn)直接裝配方式的未生效:
這是為啥呢?
2 源碼解析
就得精通這兩種注入風(fēng)格在Spring分別如何實(shí)現(xiàn)的。
2.1 收集裝配
DefaultListableBeanFactory#resolveMultipleBeans
private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) { final Class<?> type = descriptor.getDependencyType(); if (descriptor instanceof StreamDependencyDescriptor) { // 裝配stream return stream; } else if (type.isArray()) { // 裝配數(shù)組 return result; } else if (Collection.class.isAssignableFrom(type) && type.isInterface()) { // 裝配集合 // 獲取集合的元素類型 Class<?> elementType = descriptor.getResolvableType().asCollection().resolveGeneric(); if (elementType == null) { return null; } // 根據(jù)元素類型查找所有的bean Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType, new MultiElementDescriptor(descriptor)); if (matchingBeans.isEmpty()) { return null; } if (autowiredBeanNames != null) { autowiredBeanNames.addAll(matchingBeans.keySet()); } // 轉(zhuǎn)化查到的所有bean放置到集合并返回 TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); Object result = converter.convertIfNecessary(matchingBeans.values(), type); // ... return result; } else if (Map.class == type) { // 解析map return matchingBeans; } else { return null; } }
1 獲取集合類型的elementType
目標(biāo)類型定義為List users,所以元素類型為User:
2 根據(jù)元素類型找出所有Bean
有了elementType,即可據(jù)其找出所有Bean:
3 將匹配的所有的Bean按目標(biāo)類型轉(zhuǎn)化
上一步獲取的所有的Bean都以java.util.LinkedHashMap.LinkedValues
存儲,和目標(biāo)類型大不相同,所以最后按需轉(zhuǎn)化。
本案例中,需轉(zhuǎn)化為List:
2.2 直接裝配方式
DefaultListableBeanFactory#findAutowireCandidates
不再贅述。
最后就是根據(jù)目標(biāo)類型直接尋找匹配Bean名稱為users的List<user>
裝配給userController#users屬性。
當(dāng)同時滿足這兩種裝配方式時,Spring會如何處理呢?
DefaultListableBeanFactory#doResolveDependency
顯然這兩種裝配集合的方式不能同存,結(jié)合本案例:
- 當(dāng)使用收集裝配時,能找到任一對應(yīng)Bean,則返回
- 若一個都沒找到,才采用直接裝配
所以后期以List方式直接添加的user Bean都不生效!
3 修正
務(wù)必避免兩種方式共存去裝配集合!只選用一種方式即可。
比如只使用直接裝配:
只使用收集方式:
如何做到讓用戶2優(yōu)先輸出呢?
控制spring bean加載順序:
- Bean上使用@Order注解,如@Order(2)。數(shù)值越小表示優(yōu)先級越高。默認(rèn)優(yōu)先級最低。
- @DependsOn 使用它,可使得依賴的Bean如果未被初始化會被優(yōu)先初始化。
- 添加@Order(number)注解,number越小優(yōu)先級越高,越靠前聲
- 明user這些Bean時將id=2的user提到id=1之前
到此這篇關(guān)于Spring如何正確注入集合類型的文章就介紹到這了,更多相關(guān)Spring 集合類型內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java8新特性之lambda(動力節(jié)點(diǎn)Java學(xué)院整理)
這篇文章主要介紹了Java8新特性之lambda(動力節(jié)點(diǎn)Java學(xué)院整理)表達(dá)式的相關(guān)知識,包括lambda語法方面的知識,非常不錯,具有參考借鑒價值,需要的朋友參考下吧2017-06-06Spring?cloud?實(shí)現(xiàn)房源查詢功能的實(shí)例代碼
這篇文章主要介紹了Spring?cloud?實(shí)現(xiàn)房源查詢功能,本項(xiàng)目是一個多模塊項(xiàng)目,創(chuàng)建一個 Spring Initializr 項(xiàng)目 不自動添加依賴項(xiàng),完成創(chuàng)建后刪除自帶的src目錄,并在根目錄下創(chuàng)建新的maven模塊,需要的朋友可以參考下2022-09-09JAVA基于Slack實(shí)現(xiàn)異常日志報警詳解
這篇文章主要為大家介紹了JAVA基于Slack實(shí)現(xiàn)異常日志報警詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08Springboot如何使用filter對request body參數(shù)進(jìn)行校驗(yàn)
這篇文章主要介紹了Springboot如何使用filter對request body參數(shù)進(jìn)行校驗(yàn),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03Maven dependencies與dependencyManagement的區(qū)別詳解
這篇文章主要介紹了Maven dependencies與dependencyManagement的區(qū)別詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-04-04SpringCloud Eureka實(shí)現(xiàn)服務(wù)注冊與發(fā)現(xiàn)
Eureka是一種基于REST(具像狀態(tài)傳輸)的服務(wù),主要用于AWS云中定位服務(wù),以實(shí)現(xiàn)中間層服務(wù)器的負(fù)載平衡和故障轉(zhuǎn)移。本文記錄一個簡單的服務(wù)注冊與發(fā)現(xiàn)實(shí)例。感興趣的小伙伴們可以參考一下2019-01-01