使用@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 呢?

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

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

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

发现竟然只有一个值为 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)

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

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

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

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

整个转过过程就是

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

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

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

@Value注入map、List,yaml格式

使用@Value注入map、List

实体类

@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所对应的value包起来,要不然解析会失败,导致不能转成 Map<String,String>。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • spring中@value注解需要注意的问题

    首先,@value需要参数,这里参数可以是两种形式:@Value("#{configProperties['t1.msgname']}")或者@Value("${t1.msgname}"): 其次,下面我们来看看如何使用这两形式,在配置上有什么区别: 1. @Value("#{configProperties['t1.msgname']}")这种形式的配置中有"configProperties",其实它指定的是配置文件的加载对

  • Spring@Value属性注入使用方法解析

    这篇文章主要介绍了Spring@Value属性注入使用方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在使用Spring框架的项目中,@Value是使用比较频繁的注解之一,它的作用是将配置文件中key对应的值赋值给它标注的属性.在日常使用中我们常用的功能都比较简单,本篇文章系统的带大家来了解一下@Value的使用方法. @Value注入支持形式 @Value属性注入功能根据注入的内容来源可分为两类:通过配置文件的属性注入和通过非配置文件

  • Spring中利用配置文件和@value注入属性值代码详解

    1 简单属性值注入 package com.xy.test1; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @Service // 需要被注入属性值的类需要被Spring管理 public class PropertiesService1 { // 利用@Value注解,即使没有该属性或者属性文件也不会报错 // @Value输入

  • Springboot中@Value的使用详解

    Springboot通过@Value注解将配置文件中的属性注入到容器内组件中(可用在@Controller.@Service.@Configuration.@Component等Spring托管的类中) 1.普通字符串注入 例:yml中存在key: name: zs @Value注入 @Value("${name}") public String name; 当yml中的name没有对应值时,即yml中为: name: 此时字符串name的值为"" 可设置注入属性的

  • 详解Spring通过@Value注解注入属性的几种方式

    场景 假如有以下属性文件dev.properties, 需要注入下面的tag tag=123 通过PropertyPlaceholderConfigurer <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="dev.properties" /&

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

    @Value 注入 List 类型的配置属性 @Value 注解可以方便的帮助我们注入配置属性值. 那么当注入一个 List 类型时该怎么做呢? 想必大家都会知道,可以使用下面这种写法: @Value("#{'${zf.ids}'.split(',')}") private List<Integer> ids; 上面的配置简单说下就是,先使用 ${zf.ids} 拿到配置文件中 zf.ids 属性的值,然后使用 #{} 也就是 SPEL 表达式语言进行按,拆分,得到的结果转

  • Spring IOC容器Bean管理XML注入集合类型属性

    目录 一.定义数组.list.map.set类型属性 二.配置文件中进行对应配置 三.注入对象集合类型 四.提取注入集合的部分 1. 引入名称空间 util 2. 使用 util 标签完成集合注入的提取 一.定义数组.list.map.set类型属性 创建类.定义数组.list.map.set类型属性,生成对应set方法. package com.pingguo.spring5.collectiontype; import java.util.Arrays; import java.util.L

  • Spring boot将配置属性注入到bean类中

    一.@ConfigurationProperties注解的使用 看配置文件,我的是yaml格式的配置: // file application.yml my: servers: - dev.bar.com - foo.bar.com - jiaobuchong.com 下面我要将上面的配置属性注入到一个Java Bean类中,看码: import org.springframework.boot.context.properties.ConfigurationProperties; import

  • Spring boot工具类静态属性注入及多环境配置详解

    由于需要访问MongoDB,但是本地开发环境不能直接连接MongoDB,需要通过SecureCRT使用127.0.0.2本地IP代理.但是程序部署到线上生产环境后,是可以直接访问MongoDB的,因此开发好程序后,总是要修改一下MongoDB服务器的IP才能提交代码,这样很是不方便. private static final String PUBCHAT_HOST = "127.0.0.2"; // private static final String PUBCHAT_HOST =

  • Spring注入Date类型的三种方法总结

    Spring注入Date类型的三种方法总结 测试Bean: public class DateBean { private Date birthday; public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } } 方式1:利用SimpleDateFormat的构造方法注入 <?xml version="1.0&quo

  • Spring Cloud 覆写远端的配置属性实例详解

    应用的配置源通常都是远端的Config Server服务器,默认情况下,本地的配置优先级低于远端配置仓库.如果想实现本地应用的系统变量和config文件覆盖远端仓库中的属性值,可以通过如下设置: spring: cloud: config: allowOverride: true overrideNone: true overrideSystemProperties: false overrideNone:当allowOverride为true时,overrideNone设置为true,外部的配

  • 使用spring注入枚举类型作为参数

    目录 spring注入枚举类型作为参数 Spring参数注入 1.通过构造方法实现参数注入 2.通过set方法注入 3.P命名空间注入 spring注入枚举类型作为参数 //定义枚举类型 public enum ReportType { MONTH,WEEK,DAY } //使用枚举类型 public class ReportJob { private ReportType reportType; } //spring配置文件注入 <bean id="DAY" class=&qu

  • Spring的@Value注入复杂类型(通过@value注入自定义类型)

    之前写了一篇关于Spring的@Value注入的文章<介绍两种SpringBoot读取yml文件中配置数组的方法>. 里面列出了@Value和@ConfigurationProperties的对比,其中有一条是写的@value不支持复杂类型封装(数组.Map.对象等). 但是后来有小伙伴留言说他用@value测试的时候,是可以注入的数组和集合的.于是我就跟着做了一些测试,发现确实可以.但是只有在以,分割的字符串的时候才可以. 为什么用,分割的字符串可以注入数组?于是我就去一步一步的断点去走了一

  • Spring boot配置绑定和配置属性校验的方式详解

    目录 配置绑定 先建立数据配置文件 application.yml @ConfigurationProperties @Value 第一种 @Value(“${}”) 第二种@Value(“#{}”) @PropertySource 配置属性校验 @Value 与 @ConfigurationProperties对比 1. 使用位置不同 2. 功能不同 3. 松散绑定支持不同 4. SpEL 支持不同 5. 复杂类型封装 6.属性校验 7. 应用场景不同 配置绑定 所谓配置绑定”就是把配置文件中

  • Spring如何正确注入集合类型

    目录 1 注入方式 1.1 收集方式 1.2 直接装配方式 2 源码解析 2.1 收集装配 1 获取集合类型的elementType 2 根据元素类型找出所有Bean 3 将匹配的所有的Bean按目标类型转化 2.2 直接装配方式 3 修正 集合类型的自动注入是Spring提供的另外一个强大功能.我们在方便的使用依赖注入的特性时,必须要思考对象从哪里注入.怎么创建.为什么是注入这一个对象的.虽然编写框架的目的是让开发人员无需关心太多底层细节,能专心业务逻辑的开发,但是作为开发人员不能真的无脑去使

随机推荐