JAVA全系列 教程
3762个小节阅读:7094.1k
目录
C语言快速入门
JAVA全系列 教程
面向对象的程序设计语言
Python全系列 教程
Python3.x版本,未来主流的版本
人工智能 教程
顺势而为,AI创新未来
大厂算法 教程
算法,程序员自我提升必经之路
C++ 教程
一门通用计算机编程语言
微服务 教程
目前业界流行的框架组合
web前端全系列 教程
通向WEB技术世界的钥匙
大数据全系列 教程
站在云端操控万千数据
AIGC全能工具班
A A
White Night
BeanWrapper 是 基于装饰器设计模式实现的。实现了PropertyEditorRegistry接口和TypeConverter接口。
在DataBinder数据绑定时,Bean的属性绑定过程就是使用BeanWrapper实现的。
BeanWrapper只有一个实现类BeanWrapperImpl,这个类还是PropertyEditorSupport子类,所以具备类型转换的能力。
在使用DataBinder的convertIfNecessary()方法时,底层通过getTypeConverter()获取到类型转换器对象。
xxxxxxxxxx
@Override
@Nullable
public <T> T convertIfNecessary(@Nullable Object value, @Nullable Class<T> requiredType) throws TypeMismatchException {
return getTypeConverter().convertIfNecessary(value, requiredType);
}
getTypeConverter()方法中类型转换器是通过getInternaleBindingResult()获取到的。
xxxxxxxxxx
protected TypeConverter getTypeConverter() {
if (getTarget() != null) {
return getInternalBindingResult().getPropertyAccessor();
}
else {
return getSimpleTypeConverter();
}
}
getInternaleBindingResult()方法返回结果类型为AbstractPropertyBindingResult,通过断电可以看出来实际返回结果子类BeanPropertyBindingResult。
xxxxxxxxxx
protected AbstractPropertyBindingResult getInternalBindingResult() {
if (this.bindingResult == null) {
this.bindingResult = (this.directFieldAccess ?
createDirectFieldBindingResult(): createBeanPropertyBindingResult());
}
return this.bindingResult;
}
createBeanPropertyBindingResult()方法
xxxxxxxxxx
protected AbstractPropertyBindingResult createBeanPropertyBindingResult() {
BeanPropertyBindingResult result = new BeanPropertyBindingResult(getTarget(),
getObjectName(), isAutoGrowNestedPaths(), getAutoGrowCollectionLimit());
if (this.conversionService != null) {
result.initConversion(this.conversionService);
}
if (this.messageCodesResolver != null) {
result.setMessageCodesResolver(this.messageCodesResolver);
}
return result;
}
AbstractPropertyBindingResult是Errors接口和BindingResult接口的实现类。
Errors接口里面存储数据绑定和错误信息。也就是是说通过Errors可以获取到属性的信息并且给属性绑定一个错误信息。
Errors接口里面方法比较多
xxxxxxxxxx
public interface Errors {
/**
* 实际值为点(.)
*/
String NESTED_PATH_SEPARATOR = PropertyAccessor.NESTED_PROPERTY_SEPARATOR;
/**
* 返回绑定对象名字
*/
String getObjectName();
/**
* 设置嵌套路径,当有关联对象时使用
*/
void setNestedPath(String nestedPath);
/**
* 获取嵌套路径字符串类型值
*/
String getNestedPath();
/**
* 把嵌套路径放入栈中
*/
void pushNestedPath(String subPath);
/**
* 移除嵌套路径从栈中
*/
void popNestedPath() throws IllegalStateException;
/**
* 给对象绑定一个全局的错误码(errorCode)
*/
void reject(String errorCode);
/**
* 给对象绑定一个全局的错误码(errorCode)和错误信息(defaultMessage)
*/
void reject(String errorCode, String defaultMessage);
/**
* 给对象绑定一个全局错误码(errorCode)、错误参数(errorArgs),错误信息(defualtMessage)
*/
void reject(String errorCode, @Nullable Object[] errorArgs, @Nullable String defaultMessage);
/**
* 给属性绑定错误码
*/
void rejectValue(@Nullable String field, String errorCode);
/**
* 给属性绑定错误码和错误信息
*/
void rejectValue(@Nullable String field, String errorCode, String defaultMessage);
/**
* 给属性绑定错误码和错误参数及错误信息
*/
void rejectValue(@Nullable String field, String errorCode,
@Nullable Object[] errorArgs, @Nullable String defaultMessage);
/**
* 把参数(errors)实例所有内容添加到当前对象中
*/
void addAllErrors(Errors errors);
/**
* 判断是否有错误
*/
boolean hasErrors();
/**
* 返回错误的数量
*/
int getErrorCount();
/**
* 获取到所有的错误对象
*/
List<ObjectError> getAllErrors();
/**
* 是否有全局错误
*/
boolean hasGlobalErrors();
/**
* 获取全局错误信息
*/
int getGlobalErrorCount();
/**
* 获取所有全局错误实例
*/
List<ObjectError> getGlobalErrors();
/**
* 获取全局错误对象
*/
@Nullable
ObjectError getGlobalError();
/**
* 是否有属性错误
*/
boolean hasFieldErrors();
/**
* 获取属性错误个数
*/
int getFieldErrorCount();
/**
* 获取属性错误集合
*/
List<FieldError> getFieldErrors();
/**
* 获取属性错误对象
*/
@Nullable
FieldError getFieldError();
/**
* 判断某个属性是否有错误
*/
boolean hasFieldErrors(String field);
/**
* 获取某个属性错误个数
*/
int getFieldErrorCount(String field);
/**
* 获取某个属性错误集合
*/
List<FieldError> getFieldErrors(String field);
/**
* 获取某个属性错误个数
*/
@Nullable
FieldError getFieldError(String field);
/**
* 获取某个属性的值
*/
@Nullable
Object getFieldValue(String field);
/**
* 获取某个属性的类型
*/
@Nullable
Class<?> getFieldType(String field);
}
而BindingResult是Errors接口的子接口。也就是说里面也存储了错误信息和属性绑定信息。而BindingResult接口主要是为了和数据校验Validation一起使用的。所以下一章节我们就讲解一下Validation是什么。
我们继续看源码getTypeConverter()方法中获取到BindingResult后,调用getPropertyAccessor()
xxxxxxxxxx
protected TypeConverter getTypeConverter() {
if (getTarget() != null) {
return getInternalBindingResult().getPropertyAccessor();
}
else {
return getSimpleTypeConverter();
}
}
getPropertyAccessor()方法最终返回的是BeanWrapper,如果继续跟源码,可以知道createBeanWrapper()方法实际返回结果为BeanWrapperImpl。这也说明了DataBinder数据绑定时,类型转换器本质是BeanWrapper的实现类BeanWrapperImpl。使用了装饰者模式。
xxxxxxxxxx
@Override
public final ConfigurablePropertyAccessor getPropertyAccessor() {
if (this.beanWrapper == null) {
this.beanWrapper = createBeanWrapper();
this.beanWrapper.setExtractOldValueForEditor(true);
this.beanWrapper.setAutoGrowNestedPaths(this.autoGrowNestedPaths);
this.beanWrapper.setAutoGrowCollectionLimit(this.autoGrowCollectionLimit);
}
return this.beanWrapper;
}