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. 使用Eclipse将Web项目打Jar包方法

    1.对下载.安装和运行Eclipse,就不再说了: 2.找到待打包项目: 3.右键,Export-->Export: 4.选择,Jar: 5.按如图操作: 6.完成后:

  2. Uva 129 Krypton Factor

    0.这道题的输出 处理起来挺麻烦的 以后类似的可以借鉴一下 ;i<cur;i++) { && i%==) printf("\n%c",a[i]); & ...

  3. react-router

    基本的构建 import ReactRouter from 'react-router'; let {Route, Router, Link, IndexRoute} = ReactRouter.Ro ...

  4. canvas绘制

    window.onload = function(){ var can1 = document.getElementById("can1"); var ctx = can1.get ...

  5. Activiti工作流引擎参考资料

    Activiti工作流引擎使用 工作流-Activiti核心API介绍 传智播客Activiti工作流视频教程(企业开发实例讲解) 工作流引擎Activiti演示项目 http://www.kafei ...

  6. Andriod开发技巧——Fragment的懒加载

    我们在做应用开发的时候,一个Activity里面可能会以viewpager(或其他容器)与多个Fragment来组合使用,而如果每个 fragment都需要去加载数据,或从本地加载,或从网络加载,那么 ...

  7. 洛谷 P1305 新二叉树 Label:字符串的输出总是有惊喜

    题目描述 输入一串完全二叉树,用遍历前序打出. 输入输出格式 输入格式: 第一行为二叉树的节点数n. 后面n行,每一个字母为节点,后两个字母分别为其左右儿子. 空节点用*表示 输出格式: 前序排列的完 ...

  8. HDU - Pseudoforest

    Description In graph theory, a pseudoforest is an undirected graph in which every connected componen ...

  9. 神奇的莫比乌斯带(mobius)

    1.禅师和青年之间的对话 2.制作一个莫比乌斯带 3.神奇的莫比乌斯带 4.对莫比乌斯带进行简单的数学建模 1.禅师和青年之间的对话 青年问禅师:“大师,我很爱我的女朋友,她也有很多优点,但是总有几个 ...

  10. 【BZOJ】3834: [Poi2014]Solar Panels

    http://www.lydsy.com/JudgeOnline/problem.php?id=3834 题意:求$max\{(i,j)\}, smin<=i<=smax, wmin< ...