溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Spring怎么正確注入集合類型

發(fā)布時(shí)間:2021-09-15 10:45:15 來源:億速云 閱讀:147 作者:小新 欄目:開發(fā)技術(shù)

這篇文章主要介紹了Spring怎么正確注入集合類型,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

    集合類型的自動(dòng)注入是Spring提供的另外一個(gè)強(qiáng)大功能。我們?cè)诜奖愕氖褂靡蕾囎⑷氲奶匦詴r(shí),必須要思考對(duì)象從哪里注入、怎么創(chuàng)建、為什么是注入這一個(gè)對(duì)象的。雖然編寫框架的目的是讓開發(fā)人員無需關(guān)心太多底層細(xì)節(jié),能專心業(yè)務(wù)邏輯的開發(fā),但是作為開發(fā)人員不能真的無腦去使用框架。

    現(xiàn)在有一需求:存在多個(gè)用戶Bean,找出來存儲(chǔ)到一個(gè)List。

    1 注入方式

    1.1 收集方式

    多個(gè)用戶Bean定義:

    Spring怎么正確注入集合類型

    有了集合類型的自動(dòng)注入后,即可收集零散的用戶Bean:

    Spring怎么正確注入集合類型

    這樣即可完成集合類型注入:

    Spring怎么正確注入集合類型

    但當(dāng)持續(xù)增加一些user時(shí),可能就不喜歡用上述的注入集合類型了,而是這樣:

    1.2 直接裝配方式

    Spring怎么正確注入集合類型

    Spring怎么正確注入集合類型

    分開玩,大家應(yīng)該不會(huì)有啥問題,若兩種方式共存了,會(huì)咋樣?
    運(yùn)行程序后發(fā)現(xiàn)直接裝配方式的未生效:

    Spring怎么正確注入集合類型

    這是為啥呢?

    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:

    Spring怎么正確注入集合類型

    2 根據(jù)元素類型找出所有Bean

    有了elementType,即可據(jù)其找出所有Bean:

    Spring怎么正確注入集合類型

    3 將匹配的所有的Bean按目標(biāo)類型轉(zhuǎn)化

    上一步獲取的所有的Bean都以java.util.LinkedHashMap.LinkedValues存儲(chǔ),和目標(biāo)類型大不相同,所以最后按需轉(zhuǎn)化。

    本案例中,需轉(zhuǎn)化為List:

    Spring怎么正確注入集合類型

    2.2 直接裝配方式

    DefaultListableBeanFactory#findAutowireCandidates

    不再贅述。

    最后就是根據(jù)目標(biāo)類型直接尋找匹配Bean名稱為users的List<user>裝配給userController#users屬性。

    當(dāng)同時(shí)滿足這兩種裝配方式時(shí),Spring會(huì)如何處理呢?

    DefaultListableBeanFactory#doResolveDependency

    Spring怎么正確注入集合類型

    顯然這兩種裝配集合的方式不能同存,結(jié)合本案例:

    • 當(dāng)使用收集裝配時(shí),能找到任一對(duì)應(yīng)Bean,則返回

    • 若一個(gè)都沒找到,才采用直接裝配

    所以后期以List方式直接添加的user Bean都不生效!

    3 修正

    務(wù)必避免兩種方式共存去裝配集合!只選用一種方式即可。
    比如只使用直接裝配:

    Spring怎么正確注入集合類型

    只使用收集方式:

    Spring怎么正確注入集合類型

    如何做到讓用戶2優(yōu)先輸出呢?
    控制spring bean加載順序:

    1. Bean上使用@Order注解,如@Order(2)。數(shù)值越小表示優(yōu)先級(jí)越高。默認(rèn)優(yōu)先級(jí)最低。

    2. @DependsOn 使用它,可使得依賴的Bean如果未被初始化會(huì)被優(yōu)先初始化。

    3. 添加@Order(number)注解,number越小優(yōu)先級(jí)越高,越靠前聲

    4. 明user這些Bean時(shí)將id=2的user提到id=1之前

    感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“Spring怎么正確注入集合類型”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來學(xué)習(xí)!

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI