首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

【spring】spring是如何避免请求的?源码分析

2014-04-30 
【spring】spring是如何处理请求的?源码分析最近在处理一些问题的时候,突然想到spring的两个问题。1.spring是

【spring】spring是如何处理请求的?源码分析
最近在处理一些问题的时候,突然想到spring的两个问题。
1.spring是如何回调我们的controller中定义的方法的,request response model 是怎么来的?为什么先后顺序可以颠倒?
2.spring是如何帮我们注入基本类型的参数的,比如我参数中有两个String,但是参数名字不一样,一个是id,一个是type,但是spring可以直接帮我们注入进来,不需要添加任何注解,他是怎么实现的?
抱着这两个问题,我开始看spring是如何处理请求的。


首先,spring是为我们封装了servlet,所以肯定会有一个类继承HttpServlet,从这个入口开始寻找,我们就找到了DispatcherServlet ,他是HttpServlet的一个实现类。其中重写了父类的doService方法。看到方法最后有调用doDispatch(request, response);方法,到了spring的处理器。




    在这个方法中做了如下几件事情
1.寻找URL所对应的mappedHandler处理器,如果找不到的话,执行noHandlerFound方法,其中就是会返回404。
2.如果是get请求的话,并且HTTP请求头标签中包含If-Modified-Since,在发送HTTP请求时,把浏览器端缓存页面的最后修改时间一起发到服务器去,服务器会把这个时间与服务器上实际文件的最后修改时间进行比较。如果时间一致,那么返回HTTP状态码304(不返回文件内容),客户端接到之后,就直接把本地缓存文件显示到浏览器中。
3.获取到自己定义的拦截器,循环invoke拦截器。
4.回调我们所定义的mapperHandler 也就是我们再controller中所定义的处理这个请求的方法。
5.获取到返回的 MV 通过response写出。

下面主要来看下第四部,spring是怎么回调我们自己定义的controller的。



    如上配置可以看到,配置的处理器为RequestMappingHandlerAdapter。他实现了父类的handler方法,然后调用子类的handleInternal方法处理请求。



    这个方法中,主要做两件事情,
1.获取到了本次请求所对应执行方法的参数。
2.通过反射invoke 调用方法。注入参数
这里也是让我一开始很困惑的地方,因为反射只能获取到方法参数的类型,无法获取到方法参数的变量名,那spring是如何做到获取到方法参数变量名呢?我们继续往下面看。

看到spring通过getMethodArgumentValues方法获取了所有的参数列表。
    下面来看一下updateNamedValueInfo的方法,




    首先先获取了info里面的name,如果name非空的话,name=parameter.getParameterName();  , 在getParameterName方法中获取到了参数的变量名。


    这里spring通过类加载器获取到这个类的inputStream,最后通过了ClassReader获取到了类中的所有方法和方法参数,依赖于asm的jar包。ASM是一个java字节码操纵框架,它能被用来动态生成类或者增强既有类的功能。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性以及 Java 字节码(指令)。ASM从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类。具体请看
http://www.cnblogs.com/liuling/archive/2013/05/25/asm.html

    看到这里才知道,原来spring不是通过反射来获取到的,而是通过asm jar包来解析class的字节获取到了方法的参数名字,用来注入到方法中。



下面是本人看完spring源码的一点心得
1.spring 在很多地方使用了缓存Map,用于提高性能,我们再编写代码的时候是否也可以做到呢?
2.java本来是反射是不支持获取到方法参数的变量名的,spring为了提供更好的服务,通过解析class的字节码,来完成这项功能,那我们在编写代码的时候是否可以做到呢?

热点排行