23.自定义参数绑定原理
@Data
public class Person {
private String userName;
private Integer age;
private Date birth;
private Pet pet;
}
@Data
public class Pet {
private String name;
private String age;
}
form action="/saveuser" method="post">
姓名:<input name="userName" value="zhangsan"><br/>
年龄:<input name="age" value="18"><br/>
生日:<input name="birth" value="2019/12/15"><br/>
宠物姓名:<input name="pet.name" value="阿毛"><br/>
宠物年龄:<input name="pet.age" value="3"><br/>
<input type="submit" value="保存">
</form>
POJO封装过程:
1.是否支持解析
ServletModelAttributeMethodProcessor解析器解析
进入supportsArgumentResolver方法内,parameter.hasParameterAnnotation(ModelAttribute.class):是否有ModelAttribute注解,
我们没有加,进入第二个判断条件,
this.annotationNotRequired:true 这个注解不是必须的
BeanUtils.isSimpleProperty:是否是简单属性
进入isSimpleProperty方法查看怎么判断
isSimpleValueType(type):false
type.isArray():false
所以最终返回false
!BeanUtils.isSimpleProperty就为true
查看isSimpleValueType怎么判断,所以isSimpleValueType返回false
2.如何解析
进入到resolver.resolveArgument
name:person
parameter:在前面的 方法获取到了
ann:null,因为没有编住这个注解
createAttribute(name, parameter, binderFactory, webRequest):创建这个实例
attribute为空Person对象
webrequest:原生的request,
WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name);
:将原生request中的数据绑定到attribute里面
WebDataBinder :web数据绑定器,将请求参数的值绑定到指定的JavaBean里面
WebDataBinder 利用它里面的 Converters 将请求数据转成指定的数据类型。再次封装到JavaBean中
GenericConversionService:在设置每一个值的时候,找它里面的所有converter那个可以将这个数据类型(request带来参数的字符串)转换到指定的类型(JavaBean -- Integer)
byte -- > file
bindRequestParameters(binder, webRequest):经过这一步,person里面就有值
进入查看如何绑定
------------------------------------
以下是绑定过程
进入servletBinder.bind(servletRequest),mpvs拿到请求参数对
addBindValues(mpvs, request):添加额外的绑定值
进入doBind方法
进入applyPropertyValues
进入setPropertyValues,查看如何设置属性值
进入setPropertyValue
PropertyAccessor会拿到beanWrapper
然后调用wrapper这个setPropertyValue赋值,利用反射
进入processLocalProperty convertForProperty():现在拿到的值是字符串,要转换成对应的类型
进入convertForProperty
进入convertIfNeccssary,是否需要转换
进入this.typeConverterDelegate.convertIfNecessary
conversionService.canConvert(sourceTypeDesc, typeDescriptor):查看能不能转化
进入canConvert,首先需要先拿到转换器,查看如何获取
进入getConverter,首先试图从缓存中拿,如果没有再从那124个转换器寻找 ,主要是利用增强for循环遍历
然后一直放行到convert方法中,上一步已经通过getConverter得到了转换器
下一步看如何转换
进入
ConversionUtils.invokeConverter(converter, source, sourceType, targetType)转换
进入
this.converterFactory.getConverter(targetType.getObjectType()).convert(source);
最终通过工厂进行转换
剩下的参数同样的过程