Spring Boot 2.0的属性绑定
Spring Boot2.0的属性绑定
原文
从Spring boot第一个版本以来,我们可以使用@ConfigurationProperties注解将属性绑定到对象。也可以指定属性的各种不同格式。比如,person.first-name,person.firstName和PERSON_FIRSTNAME都可以使用。这个功能叫做“relaxed binding”。
不幸的是,在spring boot 1.x,“relaxed binding”显得太随意了。从而使得很难来定义准确的绑定规则和指定使用的格式。在1.x的实现中,也很难对其进行修正。比如,在spring boot 1.x中,不能将属性绑定到java.util.Set对象。
所以,在spring boot 2.0中,开始重构属性绑定的功能。我们添加了一些新的抽象类和一些全新的绑定API。在本篇文章中,我们会介绍其中一些新的类和接口,并介绍添加他们的原因,以及如何在自己的代码中如何使用他们。
Property Sources
如果你已经使用spring有一段时间,你应该对Environment比较熟悉了。这个接口继承了PropertyResolver,让你从一些PropertySource的实现解析属性。
Spring Framework提供了一些常用的PropertySource,如系统属性,命令行属性,属性文件等。Spring Boot自动配置这些实现(比如加载application.properties)。
Configuration Property Sources
比起直接使用已存在的PropertySource实现类,Spring Boot2.0引入了新的ConfigurationPropertySource接口。我们引入这个新的接口来定义“relaxed binding”规则。
该接口的主要API显得非常简单
ConfigurationProperty getConfigurationProperty(ConfigurationPropertyName name);
另外有个IterableConfigurationPropertySource变量实现了Iterable<ConfigurationPropertyNaame>,让你可以发现source包含的所有属性名称。
你可以向下面这样将Environment传给ConfigurationPropertySources:
sources = ConfigurationPropertySources.get(environment);" title="" data-original-title="复制">
Iterable<ConfigurationPropertySource> sources = ConfigurationPropertySources.get(environment);
我们同时提供了MapConfigurationPropertySource来帮你应付上面的场景。
Configuration Property Names
如果规则明确,实现"relaxed binding"会简单很多。一直使用一致的格式,而不需要去关系在source中的各种无规则的格式。
ConfigurationPropertyNames类来强制进行这些属性命名规则,例如“use lowercase kebab-case names”,在代码中使用person.first-name,在source中使用person.firstName或者PERSON_FIRSTNAME.
Origin Support
如期望的那样,ConfigurationPropertySource返回ConfigurationProperty对象,里面包含了属性的取值,另外有个可选的Origin对象。
spring boot 2.0引入了新的接口Origin,能够指出属性取值的准确位置。其中TextResourceOrigin是较为常用的实现,会提供所加载的Resource,以及对应的行。
对于.properties和.yml文件,我们写了定制的souce加载器,使得追踪成为可能。一些spring boot的功能进行了重写来追踪信息。比如,属性绑定的验证异常现在会显示:
Description:
Binding to target org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'person' to scratch.PersonProperties failed:
Property: person.name
Value: Joe
Origin: class path resource [application.properties]:1:13
Reason: length must be between 4 and 2147483647
Action:
Update your application's configuration" title="" data-original-title="复制">
APPLICATION FAILED TO START
Description:
Binding to target org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'person' to scratch.PersonProperties failed:
Property: person.name
Value: Joe
Origin: class path resource [application.properties]:1:13
Reason: length must be between 4 and 2147483647
Action:
Update your application's configuration
Binder API
org.springframework.boot.context.properties.bind.Binder类允许你使用多个ConfigurationPropertySource。准确的说,Binder使用Bindable并返回一个BindResult.
Bindable
一个Bindable可以是Java bean,或是一个复杂对象(如List<Person>).这里是一些例子
Bindable.ofInstance(existingBean);
Bindable.of(Integer.class);
Bindable.listOf(Person.class);
Bindable.of(resovableType);
Binable用来携带注解的信息,但不需要太过关注这个。
BindResult
binder会返回BindResult,和java8 stream操作返回的Optional很相似,一个BinderResult表示bind的结果。
如果你尝试获取一个没有绑定的对象,会抛出异常,另外有其他的方法来设置没有绑定时的缺省对象。
//返回LocalDate,如果没有则抛出异常
bound.get()
//返回一个格式化时间,或是“No DOB"
bound.map(dateFormatter::format).orElse("NO DOB");
//返回LocalDate或者抛出自定义异常
bound.orElseThrow(NoDateOfBirthException::new);
" title="" data-original-title="复制">
var bound = binder.bind("person.date-of-birth",Bindable.of(LocalDate.class));
//返回LocalDate,如果没有则抛出异常
bound.get()
//返回一个格式化时间,或是“No DOB"
bound.map(dateFormatter::format).orElse("NO DOB");
//返回LocalDate或者抛出自定义异常
bound.orElseThrow(NoDateOfBirthException::new);
Formatting and Conversion
大部分ConfigurationPropertySource实现将值当字符串处理。当Binder需要将值转化为其他类型时,会使用到Spring的ConversionService API。比较常用的是@NumberFormat和@DateFormat这两个注解。
spring boot 2.0也引入了一些新的注解和转换器。例如,你现在可以将4s转换成Duration。具体请参考org.springframework.boot.conver包。
BindHandler
在binding的过程中,你可能会需要实现一些额外的逻辑。BindHandler接口提供了这样的机会。每一个BindHandler有onStart, onSuccess, onFailure和 onFinish方法供重载。
spring boot提供了一些handlers,用来支持已存在的@ConfigurationProperties binding。 比如 ValidationBindHandler可以用于绑定对象的合法性校验上。
@ConfigurationProperties
如文章开头所提到的,@ConfigurationProperties是在spring boot最初就加入的功能。所以大部分人会继续使用该注解是不可避免的。
Future Work
我们计划在spring boot2.1中继续加强Binder的功能,而第一个想要支持的功能是不可变属性绑定。另外相较getters和setters的绑定,使用基于构造器的绑定来代替:
public class Person{
private final String firstName;
private final String lastName;
private final LocalDateTime dateOfBirth;
public Person(String firstName, String lastName, LocalDateTime dateOfBirth){
this.firstName = firstName;
this.lastName = lastName;
this.dateOfBirth = dateOfBirth;
}
//getters
}
Summary
我们希望在spring boot2.0 中你可以找到更好用的属性绑定功能,并考虑升级你目前的方式。
原文地址:https://segmentfault.com/a/1190000018773800?utm_source=tag-newest
Spring Boot 2.0的属性绑定的更多相关文章
- Spring Boot 2.0 的配置绑定类Bindable居然如此强大
1. 前言 在开发Spring Boot应用时会用到根据条件来向Spring IoC容器注入Bean.比如配置文件存在了某个配置属性才注入Bean : 图中红色的部分是说,只有ali.pay.v1.a ...
- Spring Boot 2.0系列文章(七):SpringApplication 深入探索
关注我 转载请务必注明原创地址为:http://www.54tianzhisheng.cn/2018/04/30/springboot_SpringApplication/ 前言 在 Spring B ...
- 详细介绍Spring Boot 2.0的那些新特性与增强
以Java 8 为基准 Spring Boot 2.0 要求Java 版本必须8以上, Java 6 和 7 不再支持. 内嵌容器包结构调整 为了支持reactive使用场景,内嵌的容器包结构被重构了 ...
- Spring Boot 2.0 升级指南
Spring Boot 2.0 升级指南 前言 Spring Boot已经发布2.0有5个月多,多了很多新特性,一些坑也慢慢被填上,最近有空,就把项目中Spring Boot 版本做了升级,顺便整理下 ...
- Spring Boot 2.0 新特性和发展方向
以Java 8 为基准 Spring Boot 2.0 要求Java 版本必须8以上, Java 6 和 7 不再支持. 内嵌容器包结构调整 为了支持reactive使用场景,内嵌的容器包结构被重构了 ...
- Spring Boot 2.0正式发布,新特性解读
作者|翟永超 Spring Boot 2.0 来啦,有哪些新特性?升级吗? 写在前面 北京时间 3 月 1 日,经过漫长的等待之后,Spring Boot 2.0 正式发布.作为 Spring 生态中 ...
- 【2.0新特性】Spring Boot 2.0新特性
以Java 8 为基准 Spring Boot 2.0 要求Java 版本必须8以上, Java 6 和 7 不再支持. 内嵌容器包结构调整 为了支持reactive使用场景,内嵌的容器包结构被重构了 ...
- Spring Boot实践——Spring Boot 2.0 新特性和发展方向
出自:https://mp.weixin.qq.com/s/EWmuzsgHueHcSB0WH-3AQw 以Java 8 为基准 Spring Boot 2.0 要求Java 版本必须8以上, Jav ...
- Spring Boot 2.0 新特性
这是一篇总结文章,主要收集 Spring Boot 2.0 相对于 Spring Boot 1.x 的新特性,本章节并不提供实践性质的源代码.在 Spring Boot 系列文章中会持续退出实践章节. ...
随机推荐
- Java学习笔记----你可能不知道那些知识,对象复制与引用
1.private ,protected,static不能用来修饰interface. 2.java在处理基本数据类型(比如int ,char,double)时,都是採用按值传递的方式运行.除此之外的 ...
- 基于百度AI人脸识别技术的Demo
编写demo之前首先浏览官方API:http://ai.baidu.com/docs#/Face-API/top 下面是源码: package com.examsafety.test; import ...
- BZOJ1202 [HNOI2005]狡猾的商人 并查集维护前缀和
1202: [HNOI2005]狡猾的商人 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1935 Solved: 936[Submit][Stat ...
- 【Codeforces】716D Complete The Graph
D. Complete The Graph time limit per test: 4 seconds memory limit per test: 256 megabytes input: sta ...
- ADT20 混淆编译
注意:一定要 android代码混淆,整了两天怎么也弄不去来,百度翻遍了也都是怎么配置cfg文件,怎么混淆成功的喜悦,我就气死了,怎么都不成功.真是气死了,不过功夫不负有心人,终究还是弄出来了. 不能 ...
- 10.05FZSZ Day2模拟总结
今天的题目难度比昨天小一些,但是太菜的我还是啥也不会. 今天的出题大佬是Heaplex,他的题目中倒是出现了ZZQ,不知道是否是本人? T1.a 期望得分30,实际得分30 这道题开场发现好像有什么小 ...
- POJ2653 Pick-up sticks 判断线段相交
POJ2653 判断线段相交的方法 先判断直线是否相交 再判断点是否在线段上 复杂度是常数的 题目保证最后答案小于1000 故从后往前尝试用后面的线段 "压"前面的线段 排除不可能 ...
- 洛谷P1291 [SHOI2002]百事世界杯之旅——期望DP
题目:https://www.luogu.org/problemnew/show/P1291 水水的经典期望DP: 输出有毒.(其实也很简单啦) 代码如下: #include<iostream& ...
- 2-4 Vue中的属性绑定和双向数据绑定
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- [Swift通天遁地]一、超级工具-(16)使用JTAppleCalendar制作美观的日历
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...