2012-09-09 21:32 26578人阅读 评论(3) 收藏 举报

版权声明:本文为博主原创文章,未经博主允许不得转载。

Blog文章地址:http://www.jmatrix.org/spring/453.html

1.      概述

对于Web开发者,MVC模型是大家再熟悉不过的了,SpringMVC中,满足条件的请求进入到负责请求分发的DispatcherServlet,DispatcherServlet根据请求url到控制器的映射(HandlerMapping中保存),HandlerMapping最终返回HandlerExecutionChain,其中包含了具体的处理对象handler(也即我们编程时写的controller)以及一系列的拦截器interceptors,此时DispatcherServlet会根据返回的HandlerExecutionChain中的handler找到支持这一处理器类型的适配器(handlerAdapter),在处理器适配器中最终会去调用控制器的请求响应方法并返回结果视图(ModelAndView),得到结果视图后,通过render方法完成结果的显示。

HanderMapping的继承体系:

HandlerAdapter的继承体系:

同样的视图解析器ViewResolver针对不同的输出格式也有一系列的实现类,具体可自己看。

2.    实现分析

以我自己的一个web项目中spring mvc的配置为例:

  1. <context:component-scan base-package="cn.ds.log" />
  2. <bean id="defaultHandlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
  3. <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
  4. </bean>
  5. <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
  6. </bean>
  7. <bean
  8. class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter">
  9. </bean>
  10. <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  11. <property name="prefix">
  12. <value>/WEB-INF/jsp/</value>
  13. </property>
  14. <property name="suffix">
  15. <value>.jsp</value>
  16. </property>
  17. </bean>

这里因为是采用全注解的方式,所以先通过context:component-scan配置让spring自定扫描的包路径,接着配置handlerMapping、handlerAdapter及ViewResolver,几乎包含了SpringMVC的配置中需要涉及的所有元素。后面需要涉及具体的HanderMapping等的实现时,将以这里配置中的实现为例进行分析,其它的大家“同理可解”。⊙﹏⊙b汗

2.1  Spring MVC初始化流程

DispatcherServlet的继承体系如:

看到它们继承自HttpServlet,你就知道初始化过程应该是从init方法开始了,整个初始化的流程为:

很简单是么?我也觉得是,至少从上面的时序图看来是这样,不过前提是你已经很了解Spring IOC的实现原理了。上面的时序图中,在5的initStragegies()中除了调用6,7的函数外,还有几个类似的初始化函数,因为这里主要是为了理解整个的流程,所以我都省略了。上面流程可能需要分析的地方就在于3,4步,我们看看initWebApplicationContext函数的实现:

  1. protected WebApplicationContext initWebApplicationContext() {
  2. WebApplicationContext rootContext =
  3. WebApplicationContextUtils.getWebApplicationContext(getServletContext());
  4. WebApplicationContext wac = null;
  5. if (this.webApplicationContext != null) {
  6. // A context instance was injected at construction time -> use it
  7. wac = this.webApplicationContext;
  8. if (wac instanceof ConfigurableWebApplicationContext) {
  9. ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
  10. if (!cwac.isActive()) {
  11. ……
  12. configureAndRefreshWebApplicationContext(cwac);
  13. }
  14. }
  15. }
  16. if (wac == null) {
  17. wac = findWebApplicationContext();
  18. }
  19. if (wac == null) {
  20. // No context instance is defined for this servlet -> create a local one
  21. wac = createWebApplicationContext(rootContext);
  22. }
  23. if (!this.refreshEventReceived) {
  24. // Either the context is not a ConfigurableApplicationContext with refresh
  25. // support or the context injected at construction time had already been
  26. // refreshed -> trigger initial onRefresh manually here.
  27. onRefresh(wac);
  28. }
  29. if (this.publishContext) {
  30. ……
  31. }
  32. return wac;
  33. }

看起来貌似有点复杂,其实理解了IOC容器的实现原理(可以看下“spring ioc源码分析”一文,⊙﹏⊙多年前弄的,这次暑假实习时又以读书报告的形式写了,感觉当年肿么可以写得这么乱……也是一种成长,不打算修改)就很简单,函数一开始会去获取WebApplicationContext对象,这个对象在ContextLoaderListener初始化IOC容器时就已经把它set到ServletContext的属性中,而且它也正是ConfigurableWebApplicationContext的实例,第一个if语句其实就是如果此时SpringIOC容器没有初始化的话就在这里启动IOC容器的初始化过程,因为看“省略(1)”中的代码你就知道,它会在这里调用refresh函数,“世人”都知道这就是IOC容器启动的入口,这里会解析配置文件springmvc-servlet.xml。

这里最终要执行onRefresh(),而这个就是SpringMVC初始化的入口。

(注:其实这里也可以配置log4j,通过其打印的info信息来看IOC与MVC的初始化顺序)

相关内容:

1. Spring MVC源码分析——请求处理,http://blog.csdn.net/shi1122/article/details/8041017

2. Spring MVC源码分析——视图解析,http://blog.csdn.net/shi1122/article/details/8586463

springmvc源码分析的更多相关文章

  1. 8、SpringMVC源码分析(3):分析ModelAndView的形成过程

    首先,我们还是从DispatcherServlet.doDispatch(HttpServletRequest request, HttpServletResponse response) throw ...

  2. 7、SpringMVC源码分析(2):分析HandlerAdapter.handle方法,了解handler方法的调用细节以及@ModelAttribute注解

    从上一篇 SpringMVC源码分析(1) 中我们了解到在DispatcherServlet.doDispatch方法中会通过 mv = ha.handle(processedRequest, res ...

  3. springMVC源码分析--ViewNameMethodReturnValueHandler返回值处理器(三)

    之前两篇博客springMVC源码分析--HandlerMethodReturnValueHandler返回值解析器(一)和springMVC源码分析--HandlerMethodReturnValu ...

  4. springMVC源码分析--HandlerMethodReturnValueHandlerComposite返回值解析器集合(二)

    在上一篇博客springMVC源码分析--HandlerMethodReturnValueHandler返回值解析器(一)我们介绍了返回值解析器HandlerMethodReturnValueHand ...

  5. springMVC源码分析--RequestParamMethodArgumentResolver参数解析器(三)

    之前两篇博客springMVC源码分析--HandlerMethodArgumentResolver参数解析器(一)和springMVC源码解析--HandlerMethodArgumentResol ...

  6. springMVC源码分析--访问请求执行ServletInvocableHandlerMethod和InvocableHandlerMethod

    在之前一篇博客中springMVC源码分析--RequestMappingHandlerAdapter(五)我们已经简单的介绍到具体请求访问的执行某个Controller中的方法是在RequestMa ...

  7. springMVC源码分析--RequestMappingHandlerAdapter(五)

    上一篇博客springMVC源码分析--HandlerAdapter(一)中我们主要介绍了一下HandlerAdapter接口相关的内容,实现类及其在DispatcherServlet中执行的顺序,接 ...

  8. springMVC源码分析--HttpRequestHandlerAdapter(四)

    上一篇博客springMVC源码分析--HandlerAdapter(一)中我们主要介绍了一下HandlerAdapter接口相关的内容,实现类及其在DispatcherServlet中执行的顺序,接 ...

  9. springMVC源码分析--SimpleControllerHandlerAdapter(三)

    上一篇博客springMVC源码分析--HandlerAdapter(一)中我们主要介绍了一下HandlerAdapter接口相关的内容,实现类及其在DispatcherServlet中执行的顺序,接 ...

  10. springMVC源码分析--SimpleServletHandlerAdapter(二)

    上一篇博客springMVC源码分析--HandlerAdapter(一)中我们主要介绍了一下HandlerAdapter接口相关的内容,实现类及其在DispatcherServlet中执行的顺序,接 ...

随机推荐

  1. Linux解压文件

    zip: 解压:unzip filename 解压到tmp文件夹:unzip filename.zip -d /tmp 查看压缩文件而不解压:unzip filename.zip -v tar.gz: ...

  2. Java类与对象的基础学习

    1. 请输入并运行以下代码,得到什么结果? public class Test{ public static void main(String args[]){ Foo obj1=new Foo(); ...

  3. Mac 显示 Finder 隐藏文件

    显示Mac隐藏文件的命令:defaults write com.apple.finder AppleShowAllFiles -bool true 隐藏Mac隐藏文件的命令:defaults writ ...

  4. eclipse 和 android studio 打包签名apk问题

    首先,我使用eclipse打包了一个签名apk 然后,我使用同一个签名文件在android studio 打包同一个项目 接下来,首先安装eclipse 打包的apk,然后安装android stud ...

  5. iOS系统架构

    1.iOS系统架构 iOS的系统架构分为四个层次 核心操作系统层 (Core OS) 它包括 内存管理 , 文件系统 , 电源管理以及一些其他的操作系统任务, 它可以直接和硬件设备进行交互 核心服务层 ...

  6. nginx负载均衡之基于客户端cookie的会话保持

    通过ip_hash做会话保持有一定的缺陷,这个是通过客户端ip来实现.同一个网络下众多客户端访问服务器会被扔到同一台机器,再或者是CDN也 会导致负载不均衡.所以要实现通过客户端cookie实现,包括 ...

  7. Hive内部表外部表转化分析(装)

    link:http://anyoneking.com/archives/127hive表分为内部表和外部表.外部表在删除的时候并不会删除到hdfs中的文件,比较安全,所以对于重要的需要进行分析的日志建 ...

  8. NOIP 2005 青蛙过河

    做题记录:2016-08-10 21:58:09 题目描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都 ...

  9. [Leetcode] Recover Binary Search Tree

    Two elements of a binary search tree (BST) are swapped by mistake. Recover the tree without changing ...

  10. 基于jquery的图片懒加载js

    function lazyload(option){ var settings={ defObj:null, defHeight: }; settings=$.extend(settings,opti ...