现象
平时使用自定义配置时一般都是通过@Value这种方式取配置值的,如果配置不存在或者书写有误spring就会启动报错。有一天需要自定义配置比较多,如果每个引用的地方都通过@Value获取配置的话不仅不方便管理而且很多重复的操作,比如改个名字就需要到处找然后挨个修改。已是就改用@ConfigurationProperties的方式将一堆配置统一放一个类里面管理。上线的时候将测试环境的配置拷到生产环境,因为是一样的,所以笃定没啥问题自信上线。结果一上就出问题,看日志知道ConfigurationProperties的值为空的,没取到配置文件的值。
解决
经过检查发现拷贝测试环境配置的时候由于不小心,少了一个空格,因为配置都是放到配置中心nacos的,所以没有提示,导致通过prefix匹配不到正确的值而为空。要是使用@Value的话启动就报错,不至于上线才发现问题了。因为 ** @ConfigurationProperties获取配置,如果配置不存在值就为空,@Value获取配置,如果配置不存在就会抛出异常 ** 。
扩展
@ConfigurationProperties这个注解大多数是在做自动装配时,自动获取配置文件配置属性值的,例如
从设计上来理解根据spring boot约定优于配置的理念,一般会设置默认值,所以@ConfigurationProperties获取配置应该是允许为空的。
spring boot作者估计也想到这样做估计会经常有写错的情况。所以就设计了一个元数据的概念,这些元数据能够为在配置application.yml或者application.properties时提供属性说明、默认值和自动补全。放在META-INF目录下spring-configuration-metadata.json文件中。自己项目里面的自定义配置可以编写一个这样的元数据文件,这样IDEA自动识别,写错了会提示。当然也可以通过spring-boot-configuration-processor工具自动扫描到@ConfigurationProperties注解的类生成元数据文件。例如spring boot的元数据如下