【根底系列】ConfigurationProperties 配置绑定中那些你不晓得的事件
在 SpringBoot 我的项目中,获取配置属性能够说是一个非常简单的事件,将配置写在aplication.yml
文件之后,咱们就能够间接通过@Value
注解来绑定并获取;此外咱们也能够将一个结构化的配置,借助@ConfigurationPorperties
绑定到一个 POJO,而后供我的项目应用,那么在应用它的时候,不知是否有想过
@ConfigurationPorperties
润饰的类如何失效- 配置参数与定义的 POJO 类型不匹配时会怎么
- 配置参数的必要性校验能够怎么反对
- 自定义的配置参数,idea 中如何主动补全
- 已废除的参数定义,怎么敌对的提醒应用方
- List/Map 格局的参数,怎么应用
- 自定义参数解析规定如何反对
如果下面这些都曾经了然于心,那么本文的帮忙将不会特地大;如果对此有所疑难,接下来将逐个进行解惑
<!-- more -->
I. 我的项目环境
本我的项目借助SpringBoot 2.2.1.RELEASE
+ maven 3.5.3
+ IDEA
进行开发
上面是外围的pom.xml
(源码能够再文末获取)
<!-- 这个依赖是干嘛的,后文会介绍 --><dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> </dependency></dependencies>
II. ConfigurationProperties 详解
1. 配置绑定
假设咱们当初自定义一个功能模块,外面有一些咱们自定义的参数,反对通过 yaml 配置文件的形式注入
首先咱们能够先定义一个配置类 BindConfig
@Data@ConfigurationProperties(prefix = "hhui.bind")public class BindConfig { private String name; private Integer age; private List<String> list; private Map<String, String> map;}
请留神下面的注解中,prefix = hhui.bind
,简略来讲就是会读取配置文件中,前缀为 hhui.bind
的属性,而后顺次赋值到这个类中
BindConfig.name = hhui.bind.name
BindConfig.age = hhui.bind.age
- ...
对应的配置文件如下
hhui: bind: name: YiHui age: 18 list: - java - c - python map: wechat: 小灰灰blog blogs: http://blog.hhui.top git: http://github.com/liuyueyi
注意事项
- 配置类必须有公共的 Setter 办法,上文中次要是借助 lombok 的
@Data
省略了 Setter 办法的显示申明而已 类的属性名与配置文件中的配置名要求匹配
- 大小写不敏感
- 反对下划线转驼峰
- 配置类不要求必须是 public
对于下面最初一点,也就表明咱们能够在主动 AutoConfiguration 类中,申明一个外部类来绑定配置信息,如下
@Configuration@EnableConfigurationProperties({AutoConfiguration.BindConfig.class})public class AutoConfiguration { @Data @ConfigurationProperties(prefix = "hhui.bind") static class BindConfig { private String name; private Integer age; private List<String> list; private Map<String, String> map; }}
2. 注册失效
咱们通过@ConfigurationProperties
润饰配置类之后,是否间接会失效呢?通常来讲,让它失效有上面三种形式
a. @Component
等注解润饰形式
间接在配置类上增加@Component
, @Configuration
等注解,让 Spring 容器扫描并加载它
@Data@Component@ConfigurationProperties(prefix = "hhui.bind")public class BindConfig {}
应用这种形式时,须要留神配置类在主动扫描的包门路下,否则可能不会被扫描(次要是作为第三方 jar 包提供服务时,可能呈现扫描不到的问题)
b. @Bean
注册
把它当成一个一般的 bean,借助 bean 注册的形式来实现,也是一个可选的计划,个别的实现形式如下
@Configurationpublic class AutoConfiguration { @Bean public BindConfig bindConfig() { return new BindConfig(); }}
c. @EnableConfigurationProperties
形式
在配置类上,增加这个注解之后,能够实现配置注册,个别常见的应用姿态如
@EnableConfigurationProperties({BindConfig.class})@Configurationpublic class AutoConfiguration {}
d. 小结
下面三种注册形式,后面两种的思路是将配置类作为 bean,第三种实现思路和被动注册 bean 统一(所以想实现被动注册 bean,能够思考它的实现逻辑)
3. 参数类型不匹配
如果咱们在配置中,一个原本心愿接管 int 类型的参数,后果实际上填了一个非整形,会怎么?
比方后面的配置类,咱们理论的配置文件将age
填 18y,来看一下最终会产生什么事件
hhui: bind: Name: YiHui AGE: 18y list: - java - c - python map: wechat: 小灰灰blog blogs: http://blog.hhui.top git: http://github.com/liuyueyi
简略演示,间接在启动类中测试一下会如何
@SpringBootApplicationpublic class Application { public Application(BindConfig config) { System.out.println(config); } public static void main(String[] args) { SpringApplication.run(Application.class); }}
参数异样之后,间接启动失败,如果对参数的要求没有那么严格,即容许失败,咱们能够通过设置ignoreInvalidFields = true
@Data@ConfigurationProperties(prefix = "hhui.bind", ignoreInvalidFields = true)public class BindConfig {}
再次执行之后,会发现失常启动,输入如下
BindConfig(name=YiHui, age=null, list=[java, c, python], map={wechat=小灰灰blog, blogs=http://blog.hhui.top, git=http://github.com/liuyueyi})
留神查看下面的 age,因为传入的参数非法,所以是 null
阐明
联合默认值 + ignoreInvalidFields
形式来反对配置的最大可用性:
- 间接在配置类中,设置属性的默认值,示意当这个配置不存在或者设置非法时,应用默认的配置
@Data@ConfigurationProperties(prefix = "hhui.bind", ignoreInvalidFields = true)public class BindConfig { private String name; private Integer age = 18; private List<String> list; private Map<String, String> map;}
再次执行输入如
BindConfig(name=YiHui, age=18, list=[java, c, python], map={wechat=小灰灰blog, blogs=http://blog.hhui.top, git=http://github.com/liuyueyi}, mainPwd=Pwd(user=一灰灰blog, pwd=yihuihui, code=9))
4. 配置解析规定
常见的配置除了根本类型之外,能嵌套自定义对象么,非根本类型又能够如何解析呢?
a. POJO,List,Map 参数类型
咱们新定义一个 Pwd 类
@Datapublic class Pwd { private String user; private String pwd; private Integer code;}
而后扩大一下BindConfig
@Data@ConfigurationProperties(prefix = "hhui.bind", ignoreInvalidFields = true)public class BindConfig { private String name; private Integer age = 18; private List<String> list; private Map<String, String> map; private Pwd mainPwd;}
这个时候 mainPwd 对应的 yaml 配置文件能够如下设置
hhui: bind: Name: YiHui AGE: 1h list: - java - c - python map: wechat: 小灰灰blog blogs: http://blog.hhui.top git: http://github.com/liuyueyi # 上面这个对应的是 BindConfg.mainPwd; 能够写成 main_pwd也能够写成mainPwd main_pwd: user: 一灰灰blog pwd: yihuihui code: 9
从下面的介绍也能够看出,对于自定义的 POJO 类是反对的,应用姿态也没什么区别
此外,对于 List 和 Map 的应用也给出了实例
b.自定义配置解析
下面咱们自定义的Pwd
类,次要借助setter
办法,将匹配的属性塞入进去;如果我的配置就是一个 json 串,能够注入到一个 POJO 类么
hhui: bind: Jwt: '{"token": "11111111123", "timestamp": 1610880489123}'
对应的 Jwt 类如下
@Datapublic class Jwt { private String token; private Long timestamp;}
这个时候如想实现下面的配置解析,能够通过实现org.springframework.core.convert.converter.Converter
接口来反对,并通过@ConfigurationPropertiesBinding
注解来表明这是个配置属性转换类,不加这个注解会不失效哦
@Component@ConfigurationPropertiesBindingpublic class JwtConverter implements Converter<String, Jwt> { @Override public Jwt convert(String source) { return JSONObject.parseObject(source, Jwt.class); }}
阐明
应用自定义的配置解析规定时,留神两点
- 实现接口
Converter
- 应用
@ConfigurationPropertiesBinding
润饰注解
Spring 提供了一些默认的配置解析规定,如
文件大小
DataSize
- 对应的 value 能够是 1B, 1KB, 1MB, 1GB...
持续时间
Duration
- 对应的 value 可已是 1ns,1us,1ms,1s,1m,1h,1d
5. 配置不存在场景
一个配置类,对应的类中没有这个属性会怎么?
如针对后面的BindConfig
,没有notExist
这个属性,然而配置文件中,却加上了这个
hhui: bind: notExist: true
实测之后,发现没有任何影响,通过查看@ConfigurationProperties
注解的成员,发现能够设置ignoreUnknownFields=false
,从字面上示意呈现了未能辨认的成员,不会略谬误,然而在理论测试中,并没有失效
6. 参数校验
参数校验能够说比拟罕用的 case 了,比方后面的配置age
,基本上不会容许这个参数能是正数,如须要对参数进行校验,咱们能够借助@Validated
来实现校验
增加 pom 依赖
<dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId></dependency>
而后再配置类上增加@Validated
,而后就能够在须要校验的字段上增加对应的限度
@Data@Validated@ConfigurationProperties(prefix = "hhui.bind", ignoreInvalidFields = true, ignoreUnknownFields = false)public class BindConfig { @Min(13) @Max(66) private Integer age = 18;}
如果咱们将 age 参数设置不满足下面的条件
hhui: bind: age: 10
再次测试会发现报如下谬误
7. IDEA 主动补全提醒
平时在 Spring 开发过程中,在 yaml 文件中增加配置时,配合 idea 有十分敌对的提醒,能够十分敌对的补全参数配置
那么咱们自定义的参数想实现这个成果应该怎么做呢?
增加文章最结尾的依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId></dependency>
增加下面的依赖之后,打包mvn clean package
,而后会发现在 META-INF 上面有个spring-configuration-metadata.json
{ "groups": [ { "name": "hhui.bind", "type": "com.git.hui.boot.bind.config.BindConfig", "sourceType": "com.git.hui.boot.bind.config.BindConfig" } ], "properties": [ { "name": "hhui.bind.age", "type": "java.lang.Integer", "sourceType": "com.git.hui.boot.bind.config.BindConfig", "defaultValue": 18 }, { "name": "hhui.bind.jwt", "type": "com.git.hui.boot.bind.config.Jwt", "sourceType": "com.git.hui.boot.bind.config.BindConfig" }, { "name": "hhui.bind.list", "type": "java.util.List<java.lang.String>", "sourceType": "com.git.hui.boot.bind.config.BindConfig" }, { "name": "hhui.bind.main-pwd", "type": "com.git.hui.boot.bind.config.Pwd", "sourceType": "com.git.hui.boot.bind.config.BindConfig" }, { "name": "hhui.bind.map", "type": "java.util.Map<java.lang.String,java.lang.String>", "sourceType": "com.git.hui.boot.bind.config.BindConfig" }, { "name": "hhui.bind.name", "type": "java.lang.String", "sourceType": "com.git.hui.boot.bind.config.BindConfig" } ], "hints": []}
而后主动补全就有了
阐明
idea 举荐增加插件Spring Assistant
,反对十分敌对的配置注入
8.小结
本文介绍了@ConfigurationProperties
润饰 POJO 类,实现配置的绑定,能够通过将这个类申明为一个一般 bean 的形式进行注册,也能够借助@EnableConfigurationProperties
来注册
在配置参数时,须要留神如果参数类型不统一,会导致我的项目启动失败;能够通过设置ConfigurationProperties#ignoreInvalidFields = true
,来防止这种场景
通过实现接口Converter
+ @ConfigurationPropertiesBinding
来自定义参数解析转换规则,能够实现各路姿态的参数解析
配置的主动提醒反对也比较简单,增加org.springframework.boot:spring-boot-configuration-processor
依赖,打包之后在 META-INF 中会多一个 json 文件spring-configuration-metadata.json
II. 其余
0. 我的项目
我的项目源码
- 工程:https://github.com/liuyueyi/spring-boot-demo
- 源码: https://github.com/liuyueyi/spring-boot-demo/tree/master/spring-boot/002-properties-bind
系列博文
- 【根底系列】实现一个自定义配置加载器(利用篇)
- 【根底系列】SpringBoot 配置信息之默认配置
- 【根底系列】SpringBoot 配置信息之配置刷新
- 【根底系列】SpringBoot 根底篇配置信息之自定义配置指定与配置内援用
- 【根底系列】SpringBoot 根底篇配置信息之多环境配置信息
- 【根底系列】SpringBoot 根底篇配置信息之如何读取配置信息
1. 一灰灰 Blog
尽信书则不如,以上内容,纯属一家之言,因集体能力无限,不免有疏漏和谬误之处,如发现 bug 或者有更好的倡议,欢送批评指正,不吝感谢
上面一灰灰的集体博客,记录所有学习和工作中的博文,欢送大家前去逛逛
- 一灰灰 Blog 集体博客 https://blog.hhui.top
- 一灰灰 Blog-Spring 专题博客 http://spring.hhui.top
- 微信公众号: 一灰灰blog