--- title: Spring 数据绑定 date: 2022-12-22 19:26:57 order: 22 categories: - Java - 框架 - Spring - Spring核心 tags: - Java - 框架 - Spring - 数据绑定 permalink: /pages/750e15b8/ --- # Spring 数据绑定 **Spring 数据绑定(Data Binding)的作用是将用户的输入动态绑定到 JavaBean**。换句话说,Spring 数据绑定机制是将属性值设置到目标对象中。 在 Spring 中,数据绑定功能主要由 `DataBinder` 类实现。此外,`BeanWrapper` 也具有类似的功能,但 `DataBinder` 额外支持字段验证、字段格式化和绑定结果分析。 ![](https://raw.githubusercontent.com/dunwu/images/master/snap/20230111150930.png) ## 快速入门 定义一个用于测试的 JavaBean ```java public class TestBean { private int num; public int getNum() { return num; } public void setNum(int num) { this.num = num; } @Override public String toString() { return "TestBean{" + "num=" + num + '}'; } } ``` 数据绑定示例 ```java public class DataBindingDemo { public static void main(String[] args) { MutablePropertyValues mpv = new MutablePropertyValues(); mpv.add("num", "10"); TestBean testBean = new TestBean(); DataBinder db = new DataBinder(testBean); db.bind(mpv); System.out.println(testBean); } } ``` ## Spring 数据绑定使用场景 - Spring `BeanDefinition` 到 Bean 实例创建 - Spring 数据绑定(`DataBinder`) - Spring Web 参数绑定(`WebDataBinder`) ## DataBinder 在 Spring 中,`DataBinder` 类是数据绑定功能的基类。`WebDataBinder` 是 `DataBinder` 的子类,主要用于 Spring Web 数据绑定,此外,还有一些 `WebDataBinder` 的扩展子类,其类族如下图所示: ![](https://raw.githubusercontent.com/dunwu/images/master/snap/20230111152225.png) DataBinder 核心属性: | 属性 | 说明 | | ---------------------- | ------------------------------ | | `target` | 关联目标 Bean | | `objectName` | 目标 Bean 名称 | | `bindingResult` | 属性绑定结果 | | `typeConverter` | 类型转换器 | | `conversionService` | 类型转换服务 | | `messageCodesResolver` | 校验错误文案 Code 处理器 | | `validators` | 关联的 Bean Validator 实例集合 | `DataBinder` 类的核心方法是 `bind(PropertyValues)`:将 PropertyValues Key-Value 内容映射到关联 Bean(target)中的属性上 - 假设 PropertyValues 中包含 name=dunwu 的键值对时, 同时 Bean 对象 User 中存在 name 属性, 当 bind 方法执行时, User 对象中的 name 属性值将被绑定为 dunwu ## Spring 数据绑定元数据 DataBinder 元数据 - PropertyValues | 特征 | 说明 | | ------------ | -------------------------------------------------------------------- | | 数据来源 | BeanDefinition,主要来源 XML 资源配置 BeanDefinition | | 数据结构 | 由一个或多个 PropertyValue 组成 | | 成员结构 | PropertyValue 包含属性名称,以及属性值(包括原始值、类型转换后的值) | | 常见实现 | MutablePropertyValues | | Web 扩展实现 | ServletConfigPropertyValues、ServletRequestParameterPropertyValues | | 相关生命周期 | InstantiationAwareBeanPostProcessor#postProcessProperties | ## Spring 数据绑定控制参数 DataBinder 绑定特殊场景分析 - 当 PropertyValues 中包含名称 x 的 PropertyValue,目标对象 B 不存在 x 属性,当 bind 方法执 行时,会发生什么? - 当 PropertyValues 中包含名称 x 的 PropertyValue,目标对象 B 中存在 x 属性,当 bind 方法执 行时,如何避免 B 属性 x 不被绑定? - 当 PropertyValues 中包含名称 x.y 的 PropertyValue,目标对象 B 中存在 x 属性(嵌套 y 属性) ,当 bind 方法执行时,会发生什么? ### DataBinder 绑定控制参数 | 参数名称 | 说明 | | ------------------- | ---------------------------------- | | ignoreUnknownFields | 是否忽略未知字段,默认值:true | | ignoreInvalidFields | 是否忽略非法字段,默认值:false | | autoGrowNestedPaths | 是否自动增加嵌套路径,默认值:true | | allowedFields | 绑定字段白名单 | | disallowedFields | 绑定字段黑名单 | | requiredFields | 必须绑定字段 | ## BeanWrapper 的使用场景 - Spring 底层 JavaBeans 基础设施的中心化接口 - 通常不会直接使用,间接用于 BeanFactory 和 DataBinder - 提供标准 JavaBeans 分析和操作,能够单独或批量存储 Java Bean 的属性(properties) - 支持嵌套属性路径(nested path) - 实现类 org.springframework.beans.BeanWrapperImpl ## Spring 底层 Java Beans 替换实现 JavaBeans 核心实现 - `java.beans.BeanInfo` - 属性(Property) - `java.beans.PropertyEditor` - 方法(Method) - 事件(Event) - 表达式(Expression) Spring 替代实现 - `org.springframework.beans.BeanWrapper` - 属性(Property) - `java.beans.PropertyEditor` - 嵌套属性路径(nested path) ## DataBinder 数据校验 DataBinder 与 BeanWrapper - bind 方法生成 BeanPropertyBindingResult - BeanPropertyBindingResult 关联 BeanWrapper ## 问题 标准 JavaBeans 是如何操作属性的? | API | 说明 | | ----------------------------- | ------------------------ | | java.beans.Introspector | Java Beans 内省 API | | java.beans.BeanInfo | Java Bean 元信息 API | | java.beans.BeanDescriptor | Java Bean 信息描述符 | | java.beans.PropertyDescriptor | Java Bean 属性描述符 | | java.beans.MethodDescriptor | Java Bean 方法描述符 | | java.beans.EventSetDescriptor | Java Bean 事件集合描述符 | ## 参考资料 - [Spring 官方文档之 Core Technologies](https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans) - [《小马哥讲 Spring 核心编程思想》](https://time.geekbang.org/course/intro/265)