使用@Value 注入 List 類型的配置屬性需要注意的 BUG
@Value 注入 List 類型的配置屬性
@Value 注解可以方便的幫助我們注入配置屬性值.
那么當(dāng)注入一個(gè) List 類型時(shí)該怎么做呢?
想必大家都會(huì)知道,可以使用下面這種寫法:
@Value("#{'${zf.ids}'.split(',')}")
private List<Integer> ids;
上面的配置簡(jiǎn)單說(shuō)下就是,先使用 ${zf.ids} 拿到配置文件中 zf.ids 屬性的值,然后使用 #{} 也就是 SPEL 表達(dá)式語(yǔ)言進(jìn)行按,拆分,得到的結(jié)果轉(zhuǎn)為 List<Integer>類型的值.
這樣做沒(méi)什么問(wèn)題,可以說(shuō)完美解決了 注入復(fù)雜類型的配置文件的屬性
那么問(wèn)題來(lái)了
如果 我們想要配置文件沒(méi)有 zf.ids屬性的時(shí)候注入一個(gè)空的 List 該怎么辦呢?
這時(shí)候你可能說(shuō)簡(jiǎn)單嘛,給 ${zf.ids}加個(gè)默認(rèn)值就好了: ${zf.ids:}
@Value("#{'${zf.ids:}'.split(',')}")
private List<Integer> ids;
如上面所示,我們使用:來(lái)給 zf.ids添加一個(gè)默認(rèn)值,為空.
那么這時(shí)候,我們的 ids 屬性值的內(nèi)容是什么呢?
是 空的 List<Integer>對(duì)象? 還是 ids 的值就是個(gè) null 呢?
我們來(lái)實(shí)踐一下:看看到底是什么?
打個(gè)斷點(diǎn),調(diào)試走起,可以看到:

竟然不是 空 List,而且有一個(gè)值,我們看下 List 中的值到底是什么:

發(fā)現(xiàn)竟然只有一個(gè)值為 null 的元素 !
跟蹤源碼查看 @Value("#{'${zf.ids:}'.split(',')}") 的解析過(guò)程
其中最關(guān)鍵的一步就是下面整個(gè)方法org.springframework.beans.TypeConverterDelegate#convertIfNecessary(java.lang.String, java.lang.Object, java.lang.Object, java.lang.Class, org.springframework.core.convert.TypeDescriptor)

會(huì)發(fā)現(xiàn): ${zf.ids:) 被解析為 "" 一個(gè)空的字符串;
然后調(diào)用 SpEL 再次解析: #{''.split(',')} 即 返回一個(gè)數(shù)組,這個(gè)數(shù)組只有一個(gè)空的字符串

然后 Spring 會(huì)運(yùn)用一系列的 Converter 進(jìn)行類型轉(zhuǎn)換,關(guān)鍵就在這一步:
String[] --> List<Integer> 時(shí), 把數(shù)組中的空字符串轉(zhuǎn)為 Integer 類型時(shí),由于不能傳喚,默認(rèn)就是個(gè) null
整個(gè)轉(zhuǎn)過(guò)過(guò)程就是
[""] --> {""} --> {null}
最后我們就得到了一個(gè)只有一個(gè) null 值的 List 集合!
至此,真相大白,在使用 @Value("#{'${zf.ids:}'.split(',')}") 注入 List 屬性的時(shí)候尤其需要注意這個(gè)問(wèn)題,搞不好就是個(gè)線上 bug ! ! !
@Value注入map、List,yaml格式
使用@Value注入map、List
實(shí)體類
@Value("#{'${list}'.split(',')}")
private List<String> list;
@Value("#{${maps}}")
private Map<String,String> maps;
配置文件
list: topic1,topic2,topic3
maps: "{key1: 'value1', key2: 'value2'}"
ps:注意上面的map解析中,一定要用""把map所對(duì)應(yīng)的value包起來(lái),要不然解析會(huì)失敗,導(dǎo)致不能轉(zhuǎn)成 Map<String,String>。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java結(jié)構(gòu)型設(shè)計(jì)模式之組合模式詳解
組合模式,又叫部分整體模式,它創(chuàng)建了對(duì)象組的數(shù)據(jù)結(jié)構(gòu)組合模式使得用戶對(duì)單個(gè)對(duì)象和組合對(duì)象的訪問(wèn)具有一致性。本文將通過(guò)示例為大家詳細(xì)介紹一下組合模式,需要的可以參考一下2022-09-09
SpringBoot實(shí)現(xiàn)優(yōu)雅停機(jī)的流程步驟
優(yōu)雅停機(jī)(Graceful Shutdown) 是指在服務(wù)器需要關(guān)閉或重啟時(shí),能夠先處理完當(dāng)前正在進(jìn)行的請(qǐng)求,然后再停止服務(wù)的操作,本文給大家介紹了SpringBoot實(shí)現(xiàn)優(yōu)雅停機(jī)的流程步驟,需要的朋友可以參考下2024-03-03
IDEA下Servlet可能出現(xiàn)404的一些情況
相信有很多小伙伴遇到報(bào)錯(cuò)都不知道怎么處理,今天特地整理了這篇文章,文中對(duì)IDEA下Servlet可能出現(xiàn)404的一些情況作了詳細(xì)的介紹,需要的朋友可以參考下2021-06-06
Hadoop之NameNode Federation圖文詳解
今天小編就為大家分享一篇關(guān)于Hadoop之NameNode Federation圖文詳解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-01-01
MyBatis-Plus+達(dá)夢(mèng)數(shù)據(jù)庫(kù)實(shí)現(xiàn)高效數(shù)據(jù)持久化的示例
這篇文章主要介紹了MyBatis-Plus和達(dá)夢(mèng)數(shù)據(jù)庫(kù)實(shí)現(xiàn)高效數(shù)據(jù)持久化,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-08-08
Java mutable對(duì)象和immutable對(duì)象的區(qū)別說(shuō)明
這篇文章主要介紹了Java mutable對(duì)象和immutable對(duì)象的區(qū)別,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
Java8接口中引入default關(guān)鍵字的本質(zhì)原因詳析
Default方法是在java8中引入的關(guān)鍵字,也可稱為Virtual extension methods—虛擬擴(kuò)展方法,這篇文章主要給大家介紹了關(guān)于Java8接口中引入default關(guān)鍵字的本質(zhì)原因,需要的朋友可以參考下2022-01-01

