Spring源码深度解析(十一)SpringMVC源码解析(三)参数绑定机制
在上一章节,笔者对SpringMVC核心源码做了详细分析,并提出了一个比较关键的问题,SpringMVC如何将客户端的(key-value)数据和映射方法的参数进行绑定,本章通过由浅至深的方式一起和读者了解数据绑定的相关信息。
首先还是回到我们的实例:
简单介绍下,这是上篇文章使用的案例,只是我们添加了一个参数Integer id,然后我们在url链接上加上了?id=123,注意这个id=xxx是字符的形式,也就是说,SpringMVC将字符形式的id=123转换成了Integer形式,下面我们就来了解SpringMVC是如何实现这种方式的。
数据绑定
首先我们看一个Demo,新建两个类,一个存储三个属性,另外一个进行测试
@Controller
public class UserController {
private String name;
private Long id;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
测试类
public class MyBeanFactoryPostProcessor {
public static void main(String[] args) {
UserController userController=new UserController();
DataBinder dataBinder= new DataBinder(userController,"userController");
// 创建数据源
Map<String,String> map = new HashMap();
map.put("name","帅哥");
map.put("id","123");
map.put("age","123456");
PropertyValues propertyValues=new MutablePropertyValues(map);
dataBinder.bind(propertyValues);
System.out.println(userController);
}
}
我们先看执行结果再简单解释下它们的含义
通过结果我们可以看到,我们的数据源已经绑定在了我们的userController对象里面,注意我们属性的类型,例如id是Integer类型,我们map添加的值是字符串类型,回过来我们再看看它是怎么实现的,实现新建一个DataBinder类,将我们的对象传进去
然后创建了一个MutablePropertyValues,这个MutablePropertyValues其实内部有一个List用来存储属性
这个属性采用 key-value的方式存放,方便获取
然后执行dataBinder.bind(propertyValues);绑定成功,这行代码其实做了很多事情,笔者会在下一章节详细介绍数据绑定的底层到底做了哪些事情,这里不做太多描述,只简单介绍下,我们的数据从字符型变成Integer类型,显然需要通过数据转换的方式将数据进行转换,这就牵扯到另外一个重要的点-数据转换,Spring内部有大量的内建转换类来实现通过我们返回的对象类型找到具体的转换类,从而达到转换的效果,如果没有明白暂且不必深入研究,下个章节笔者会详细说明,好么我们了解了数据绑定的基本应用后接下来我们会到SpringMVC的参数绑定。
SpringMVC参数绑定源码解析
在对数据绑定有所了解后,相信读者应该能够感受到SpringMVC的参数绑定过程已经有些眉目,接下来我们通过源码的方式对参数绑定进行详细分析,还是回到我们的SpringMVC项目,我们将代码停在
看过前面两章的朋友都知道这里是反射执行我们的方法,我们继续跟踪
在跟踪
再跟
再跟
在跟
最后跟踪到这里
然后我们看一下request的里面有一个map
可以很清晰的看到这里的id=123是字符串的类型通过http协议传递过来,再看看参数args[i]为空。
执行完这段代码:
这里已经将我们传递的字符串转换为Integer类型并取得传递的值,拿到传递的值后我们再看
这里会获取我们的传递的值反射执行我们的方法,
好了,这里再次回到我们所执行的方法并获取了参数的值,现在我们回到
注意这个this.dataBinderFactory,可以看到里面有很多的转换器,先记住这些转换器
我们跟进一步了解SpringMVC如何实现的,跟进去
再跟
然后一直跟踪convertIfNecessary,直到
然后这里的conversionService我们看下
这里包含了非常多的转换方式,然后进入conversionService.convert();
这里通过我们传递的类型找到了我们需要到的转换器,通过这转换器就可以获取我们所需要转换的值,好了,对于SpringMVC参数绑定机制已经做了详细分析,其实就是通过Spring内建的数据转换机制再进行绑定,对于数据绑定、数据转换的内容并没有做出完整分析,我们回到convertIfNecessary方法,其实PropertyEditor也是数据转换的实现方式之一
而PropertyEditor是来自于java.beans,那么Spring为什么有自己内建一个转换器呢?笔者在下一章节详细介绍数据绑定的源码以及数据转换的内容。