0
点赞
收藏
分享

微信扫一扫

@Value 注入 List 类型的配置属性需要注意的 BUG


@Value 注入 List 类型的配置属性

​@Value​​ 注解可以方便的帮助我们注入配置属性值.

那么当注入一个 List 类型时该怎么做呢?

想必大家都会知道,可以使用下面这种写法:

@Value("#{'${zf.ids}'.split(',')}")
private List<Integer> ids;

上面的配置简单说下就是,先使用 ​​${zf.ids}​​​ 拿到配置文件中 ​​zf.ids​​​ 属性的值,然后使用 ​​#{}​​​ 也就是 SPEL 表达式语言进行按​​,​​​拆分,得到的结果转为 ​​List<Integer>​​类型的值.

这样做没什么问题,可以说完美解决了 注入复杂类型的配置文件的属性

那么问题来了

如果 我们想要配置文件没有 ​​zf.ids​​属性的时候注入一个空的 List 该怎么办呢?

这时候你可能说简单嘛,给 ​​${zf.ids}​​​加个默认值就好了: ​​${zf.ids:}​

@Value("#{'${zf.ids:}'.split(',')}")
private List<Integer> ids;

如上面所示,我们使用 ​​:​​​来给 ​​zf.ids​​添加一个默认值,为空.

那么这时候,我们的 ids 属性值的内容是什么呢?

是 空的 List<Integer>对象? 还是 ids 的值就是个 null 呢?

我们来实践一下:看看到底是什么?

打个断点,调试走起,可以看到:

@Value 注入 List 类型的配置属性需要注意的 BUG_spring

竟然不是 空 List,而且有一个值,我们看下 List 中的值到底是什么:

@Value 注入 List 类型的配置属性需要注意的 BUG_数组_02

发现竟然只有一个值为 null 的元素 !

跟踪源码查看 ​​@Value("#{'${zf.ids:}'.split(',')}")​​ 的解析过程

其中最关键的一步就是下面整个方法org.springframework.beans.TypeConverterDelegate#convertIfNecessary(java.lang.String, java.lang.Object, java.lang.Object, java.lang.Class, org.springframework.core.convert.TypeDescriptor)

@Value 注入 List 类型的配置属性需要注意的 BUG_数组_03


会发现: ​​${zf.ids:)​​​ 被解析为 ​​""​​ 一个空的字符串;

然后调用 SpEL 再次解析: ​​#{''.split(',')}​​ 即 返回一个数组,这个数组只有一个空的字符串

@Value 注入 List 类型的配置属性需要注意的 BUG_bug_04


然后 Spring 会运用一系列的 Converter 进行类型转换,关键就在这一步:

​String[]​​​ --> ​​List<Integer>​​ 时, 把数组中的空字符串转为 Integer 类型时,由于不能传唤,默认就是个 null,

整个转过过程就是

[""] --> {""} --> {null}

最后我们就得到了一个只有一个 null 值的 List 集合!

至此,真相大白,在使用 ​​@Value("#{'${zf.ids:}'.split(',')}")​​ 注入 List 属性的时候尤其需要注意这个问题,搞不好就是个线上 bug ! ! !


举报

相关推荐

0 条评论