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"
  3. class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
  4. <bean
  5. class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
  6. </bean>
  7. <bean
  8. class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
  9. </bean>
  10. <bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter">
  11. </bean>
  12. <bean id="viewResolver"
  13. class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  14. <property name="prefix">
  15. <value>/WEB-INF/jsp/</value>
  16. </property>
  17. <property name="suffix">
  18. <value>.jsp</value>
  19. </property>
  20. </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 -&gt; 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 -&gt; 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 -&gt; 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的初始化顺序)

springmvc源码解析-初始化的更多相关文章

  1. SpringMVC源码解析- HandlerAdapter - ModelFactory(转)

    ModelFactory主要是两个职责: 1. 初始化model 2. 处理器执行后将modle中相应参数设置到SessionAttributes中 我们来看看具体的处理逻辑(直接充当分析目录): 1 ...

  2. SpringMVC源码解析- HandlerAdapter - ModelFactory

    ModelFactory主要是两个职责: 1. 初始化model 2. 处理器执行后将modle中相应参数设置到SessionAttributes中 我们来看看具体的处理逻辑(直接充当分析目录): 1 ...

  3. springMVC源码解析--ViewResolver视图解析器执行(三)

    之前两篇博客springMVC源码分析--ViewResolver视图解析器(一)和springMVC源码解析--ViewResolverComposite视图解析器集合(二)中我们已经简单介绍了一些 ...

  4. SpringMVC源码解析- HandlerAdapter初始化

    HandlerAdapter初始化时,主要是进行注解解析器初始化注册;返回值处理类初始化;全局注解@ControllerAdvice内容读取并缓存. 目录: 注解解析器初始化注册:@ModelAttr ...

  5. springMVC源码解析--ViewResolverComposite视图解析器集合(二)

    上一篇博客springMVC源码分析--ViewResolver视图解析器(一)中我们介绍了一些springMVC提供的很多视图解析器ViewResolver,在开发的一套springMVC系统中是可 ...

  6. SpringMVC源码解析

    一:springmvc运行过程: 1. dispatcherServlet 通过 HandlerMapping 找到controller2. controller经过后台逻辑处理得到结果集modela ...

  7. 深入了解SpringMVC源码解析

    Spring MVC源码解析 Spring MVC的使用原理其实是通过配置一个Servlet来接管所有的请求,所有的请求由这个Servlet来进行分发处理. 我们可以从web.xml里面看出这一点 & ...

  8. springMVC源码解析--HandlerMethodArgumentResolverComposite参数解析器集合(二)

    上一篇博客springMVC源码分析--HandlerMethodArgumentResolver参数解析器(一)中我们已经介绍了参数解析相关的东西,并且也提到了HandlerMethodArgume ...

  9. springmvc源码解析MvcNamespaceHandler之<mvc:view-resolvers>

    说在前面 本次主要介绍springmvc配置解析. springmvc配置解析 本次介绍MvcNamespaceHandler. 进入到这个方法org.springframework.web.serv ...

随机推荐

  1. C# 对象相等性判断和同一性判断

    在日常开发中经常需要编写代码比较不同的对象.例如,有时需要将对象都放到一个集合中,并编写代码对集合中的对象进行排序.搜索或者比较. System.Object类有两个Equals方法,如下: 1.实例 ...

  2. Linux的管道命令

    Linux的管道命令 管道命令(Pipe) 管道命令用"|"来表示,管道命令需要接收前一个命令的输出来进行操作,但不能处理前一个命令的错误. //选取界面:cut,grep cut ...

  3. 【jQuery源码】工具函数

    //扩展工具函数 jQuery.extend({ // Unique for each copy of jQuery on the page expando: "jQuery" + ...

  4. PlanetTogether APS安装与配置

    一.PT 安装 1.PT Server与Client的下载 下载网址:https://download.planettogether.com/ 2.安装.net framework 4.6.2 安装P ...

  5. OpenGL11-绘制汉字最高效方法(使用Freetype)(代码已更新)

    最新版本,之前的版本有些文件没有打包 视频教程请关注 http://edu.csdn.net/lecturer/lecturer_detail?lecturer_id=440 OpenGL本身并没有绘 ...

  6. PHP面向对象常见符号总结($this-> 、self ::)

    转载:http://wyllife.blog.163.com/blog/static/4116390120116223528180/ 在php中常见的对象符号 1.$this this是指向当前对象的 ...

  7. ruby 数据sql操作

    ActiveRecord ActiveRecord 是 Rails 的 ORM 元件,負責與資料庫溝通,讓我們可以用物件導向的語法操作資料庫.在”打造 CRUD 應用程式”一章中提到的對應概念如下: ...

  8. 数组操作方法中的splice()和concat() 以及slice()

    1.splice()方法是修改Array的'全能方法',它可以从指定的索引开始删除若干元素,然后再从该位置添加若干元素,其中有三个参数(x,y,z) x:从索引x开始操作数组; y:0或不为0,当为0 ...

  9. 马尔科夫随机场(Markov Random Field)

    马尔可夫随机场(Markov Random Field),它包含两层意思:一是什么是马尔可夫,二是什么是随机场. 马尔可夫过程可以理解为其当前的状态只与上一刻有关而与以前的是没有关系的.X(t+1)= ...

  10. vue权限路由实现方式总结

    使用全局路由守卫 实现 前端定义好路由,并且在路由上标记相应的权限信息 const routerMap = [ { path: '/permission', component: Layout, re ...