`
Kingson_Wu
  • 浏览: 111329 次
文章分类
社区版块
存档分类
最新评论

Spring源码阅读之数据自动绑定

 
阅读更多

SpringMVC的调用过程:
DispatcherServlet ——> 根据url找到相应的Controller,反射方式调用Controller相应的方法。

研究下面两种调用方式:

    @RequestMapping("/baseType")
    public User baseType(int count, long id) {
        User user = new User();
        user.setId(id);
        user.setName("zhang");
        return user;
    }

    @RequestMapping("/object")
    public User object(User user) {
        return user;
    }

上述代码中,基本类型参数以及Java Bean参数,spring都能进行自动数据绑定。

对于第一种基本数据类型的,假如请求url为http://localhost:8080/user/baseType?count=2&id=5,url参数能自动绑定到后端方法相应名字的参数,正如上面所说的,Controller的方法是反射调用的,因此通过反射取得的方法是不会保存方法参数的参数名的,那么在反射调用的时候是怎么能够对应参数名进行传递的呢?
通过debug方式阅读spring的源码(请求过程中debug,以及容器启动过程中debug),重点查看了
DefaultParameterNameDiscoverer,
ConstructorResolver,
AspectJAdviceParameterNameDiscoverer, LocalVariableTableParameterNameDiscoverer,
PrioritizedParameterNameDiscoverer这几个类发现,spring在启动的时候通过类似asm的方式(没采用asm库)从class文件中读取了方法的参数名,并保存到相应的对象缓存中。这里我还没有仔细研究,我的猜测是class文件是有保存方法参数的参数名的,另外我记得javaassist也是通过读取class文件获取方法的参数名的(但是自己用javac生成的class文件貌似没保存参数名)。后续需要研究一下原生java如何解析class文件内容。

在idea的java compiler中加入 -g:none ,再跑起来,调用url,会报错:
java.lang.IllegalArgumentException: Name for argument type [int] not available, and parameter name information not found in class file either.

由此说明,使用maven编译打包时回把方法的参数名信息加入class文件的,也就是说asm读取参数名字时从class文件获取的。


spring-core中有个ParameterNameDiscoverer就是用来获取参数名的,底层用的是asm解析,但是接口方法的参数名无法得到,即只能是非接口类的方法参数名可以
ParameterNameDiscoverer pnd=new DefaultParameterNameDiscoverer();
String[] parameterNames=pnd.getParameterNames(用反射获取到的方法对象);//返回的就是方法中的参数名列表了
http://bbs.csdn.net/topics/391054482?page=1

Java运行时通过asm读取方法参数名:
http://www.oschina.net/code/snippet_2438265_54195
asm获取参数名的原理??

利用javassist获取java的方法参数名:
http://www.tuicool.com/articles/jMjaIr

java如何获取方法参数名:http://blog.csdn.net/mhmyqn/article/details/47294485

/**
* javac -g:none ,加上这个参数就没有了
* —
* javac -g:vars
* 以及
* mvn clean install 都可以
*/
反射是取不到的,如果在编译时使用默认选项的话。javac带有-g:vars编译参数的话,局部变量及方法形式参数名会在字节码中保存着,但是Java代码是访问不到的。
如果需要抽取字节码中的形式参数名称需要自己去了解JVM字节码规范自己去解析!


对于第二种Java Bean参数自动绑定的,因为是是对象,并不需要上述的参数名,但是需要通过反射方式设值。通过查看源码,发现确实是通过反射方式设值的,但是,正如大家一直所强调的,反射的效率较低,能不用反射尽量别用,但是spring为什么频繁用反射,而且现在每一次请求都是通过反射来赋值,那岂不是效率很低?
反射方法缓存
通过进一步查看代码发现,虽然第一次请求同过反射方式生成方法,但是所生成的方法会被保存到相应的对象缓存,当请求再次发生,调用相同的方法时,方法并不需要重新通过反射生成,而是直接从缓存中取(其实就是Map或List),不过还是通过此方法代理调用。

其实无论是DispatcherServlet通过反射调用Controller的方法,还是JavaBean参数反射调用赋值,需要反射调用的方法都是只生成一次(之后保存在缓存),而反射调用才是多次重复的。所以我的理解是生成反射方法才是效率低的,而方法的代理调用并不会太影响性能。

<script type="text/javascript"> $(function () { $('pre.prettyprint code').each(function () { var lines = $(this).text().split('\n').length; var $numbering = $('<ul/>').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($('<li/>').text(i)); }; $numbering.fadeIn(1700); }); }); </script>
分享到:
评论

相关推荐

    Spring+MVC数据绑定大全+

    Spring MVC 数据绑定大全 Spring MVC 框架提供了强大的数据绑定机制,帮助开发者快速地将 HTTP 请求中的数据绑定到 JavaBean 对象中。数据绑定是指将 HTTP 请求中的参数转换为 Java 对象的过程。在 Spring MVC 中,...

    spring源代码解析

    对于一个Spring激活的web应用程序,可以通过使用Spring代码声明式的指定在web应用程序启动时载入应用程序上下文(WebApplicationContext),Spring的ContextLoader是提供这样性能的类,我们可以使用 ...

    spring mvc 参数绑定漏洞

    NULL 博文链接:https://yfm049.iteye.com/blog/860494

    Spring MVC注解与数据绑定(含源码及结果图)

    1、有如下一个订单信息页面order.jsp(置于/WEB-INF/jsp目录下),按以下步骤实现一个使用POJO类型完成表单数据传输的SpringMVC数据绑定项目。 (1) 创建一个Order类来封装上述订单信息,其中各个属性的名称和数据类型...

    Spring In Action MVC 提交表单(2)-数据绑定和数据校验

    NULL 博文链接:https://wujiu.iteye.com/blog/2012877

    JAVA上百实例源码以及开源项目源代码

     Java绘制图片火焰效果,源代码相关注释:前景和背景Image对象、Applet和绘制火焰的效果的Image对象、Applet和绘制火焰的效果的Graphics对象、火焰效果的线程、Applet的高度,图片到图片装载器、绘制火焰效果的X坐标...

    Spring-Reference_zh_CN(Spring中文参考手册)

    5. 校验,数据绑定,BeanWrapper,与属性编辑器 5.1. 简介 5.2. 使用Spring的Validator接口进行校验 5.3. 从错误代码到错误信息 5.4. Bean处理和BeanWrapper 5.4.1. 设置和获取属性值以及嵌套属性 5.4.2. 内建的...

    Spring中文帮助文档

    5. 校验,数据绑定,BeanWrapper,与属性编辑器 5.1. 简介 5.2. 使用Spring的Validator接口进行校验 5.3. 从错误代码到错误信息 5.4. Bean处理和BeanWrapper 5.4.1. 设置和获取属性值以及嵌套属性 5.4.2. 内建...

    Spring 2.0 开发参考手册

    目录 前言 1. 简介 1.1. 概览 1.2. 使用场景 2. Spring 2.0 的新特性 2.1. 简介 ... 源代码级的元数据类型 20.3.5. 接口AutodetectCapableMBeanInfoAssembler 20.3.6. 用Java接口定义管理接口 ...

    Spring API

    5. 校验,数据绑定,BeanWrapper,与属性编辑器 5.1. 简介 5.2. 使用Spring的Validator接口进行校验 5.3. 从错误代码到错误信息 5.4. Bean处理和BeanWrapper 5.4.1. 设置和获取属性值以及嵌套属性 5.4.2. 内建...

    Spring框架源码

    Spring框架的源码,可绑定到Eclipse,对开发和学习都很有帮助,有用的下吧

    spring chm文档

    5. 校验,数据绑定,BeanWrapper,与属性编辑器 5.1. 简介 5.2. 使用Spring的Validator接口进行校验 5.3. 从错误代码到错误信息 5.4. Bean处理和BeanWrapper 5.4.1. 设置和获取属性值以及嵌套属性 5.4.2. 内建...

    毕设新作-基于spring-mvc框架实现仓库管理系统完整源码+项目说明.zip

    基于spring-mvc框架实现仓库管理系统完整源码+项目说明.zip 1、通过spring security实现的RBAC权限的模型基础上实现权限、角色、资源的管理,实现根据数据库动态分配权限的功能,对未登录及未授权的操作进行拦截。在...

    Apache CXF之结合Spring配置发布WebServices(Aegis数据绑定)

    NULL 博文链接:https://goooooooo.iteye.com/blog/463596

    Spring AOP 动态多数据源的实例详解

    例如在一个spring和Mybatis的框架的项目中,我们在spring配置中往往是配置一个dataSource来连接数据库,然后绑定给sessionFactory,在dao层代码中再指定sessionFactory来进行数据库操作。   正如上图所示,每一块...

    Spring MVC+Maven 实现前端和后台交互源码

    这是结合博客的源码,链接是:http://blog.csdn.net/u012660464/article/details/53508757 。名为:Spring MVC+Maven 实现同一项目的前端和后台交互,该源码示例了前端和后台如何进行参数的绑定传递。

    基于Spring Boot + Mybatis+Vue开发实习生招聘网站源代码+数据库毕业设计

    基于Spring Boot + Mybatis+Vue开发实习生招聘网站源代码+数据库毕业设计 前端Vue.js实现双向数据绑定; 后端基于用户和基于项协同过滤推荐算法实现职位推荐;

    Spring in Action(第2版)中文版

    第1章开始spring之旅 1.1spring是什么 1.2开始spring之旅 1.3理解依赖注入 1.3.1依赖注入 1.3.2di应用 1.3.3企业级应用中的依赖注入 1.4应用aop 1.4.1aop介绍 1.4.2aop使用 1.5小结 第2章基本bean装配 ...

Global site tag (gtag.js) - Google Analytics