一.大体流程:
①启动web容器(tomcat,也叫servlet容器)
②WebApplicationContext的servlet和Web容器监听器
配置:在web.xml中配置如下:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:smart-context.xml
</param-value>
</context-param>
<!--负责启动spring容器的监听器 还可以声明自启动的Servlet ContextLoaderServlet-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
默认加载配置文件为:/WEB-INF/applicationContext.xml
最终结果:创建spring的IoC容器(默认WebApplicationContext)(根root上下文)与web容器结合。
PS:关于是否有ContextLoaderListener的解释:推荐阅读 博客1 博客2
该IoC容器主要功能:
1、如上配置是Spring集成Web环境的通用配置;一般用于加载除Web层的Bean(如DAO、Service等),以便于与其他任何Web框架集成。
contextConfigLocation:表示用于加载Bean的配置文件;
contextClass:表示用于加载Bean的ApplicationContext实现类,默认WebApplicationC
2、ContextLoaderListener初始化的上下文加载的Bean是对于整个应用程序共享的,不管是使用什么表现层技术,一般如DAO层、Service层Bean;
③配置前端控制器
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:default_servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
默认配置文件地址:WEB-INF文件路径下查找一个文件,名为[servlet-name]-servlet.xml
最终结果:产生Spring MVC 持有的IoC容器(WebApplicationContext--默认使用XMLWebApplicationContext ),如果有根上下文,就会将springMVC 的上下文当做root上下文的子(继承了父)。
该IoC上下文的作用:
1、供Spring Web MVC的集中访问点,而且负责职责的分派,而且与Spring IoC容器无缝集成,从而可以获得Spring的所有好处。
2、DispatcherServlet初始化的上下文加载的Bean是只对Spring Web MVC有效的Bean,如Controller、HandlerMapping、HandlerAdapter等等,该初始化上下文应该只加载Web相关组件。
二.详细流程
Part1:Web容器的启动
web容器(比如tomcat、jboss、weblogic等)启动的时候,它会为每个web应用程序创建一个ServletContext对象 它代表当前web应用的上下文(注意:是每个web应用有且仅创建一个ServletContext,一个web应用,就是你一个web工程)。一个web中的所有servlet共享一个ServletContext对象,所以可以通过ServletContext对象来实现Servlet之间的通讯。在一个继承自HttpServlet对象的类中,可以通过this.getServletContext来获取。
Part2:SpringIoC容器的启动
① 条件:SpringIoc是一个独立的模块,并不是直接在web容器中发挥作用的,如果在web中使用IoC容器,需要spring为IoC设计一个启动过程,把IoC容器的导入,也就是说IoC容器的导入,是伴随着Web容器启动过程一起进行的。
② 如何连接web容器(以tomcat为例)和Spring呢?
1、<listener>:
ContextLoaderListener:监听器负责完成IoC容器在web环境中的启动工作,提供了在web容器中对spring的接口,这些接口与web容器耦合是通过ServletContext(为Ioc容器提供了一个宿主容器)来实现的。
2、<context-param>:
用来指定SpringIoC容器读取Bean定义的XML文件路径。配置文件中可以看到Spring应用的Bean配置
③启动过程:
1. 启动方式包括3种,这里要讲的事Web容器中IoC的启动方式。(其他两种参考博客)
2. ContextLoaderListener/ContextLoader/ServletContextListener
ContextLoaderListener核心是实现了 ServletContextListener 的contextInitialized(建立WebApplicationContext,进而获得ServletContext的引用的过程)和contextDestroyed方法,该方法分别调用了 ContextLoader里面的initWebApplicationContext和closeWebApplicationContext方法。
所以是ContextLoader 实现了这个监听器!
3、具体过程:
先判WebApplicationContext是否已存在,不存在的话则初始化一个XmlWebApplicationContext(WebApplicationContext的子类),并把该实例put到 currentContextPerThread 中。而初始化 XmlWebApplicationContext 时,就跟我们使用 new ClassPathXmlApplicationContext(contextConfigLocation)一样。
将我们配置的各种bean都添加到XmlWebApplicationContext中,所以我们知道 ApplicationContext 提供各种 getBean的方法。
并且可以发现 ContextLoader还提供了获取当前 WebApplicationContext的静态方法:之所以能获取,是因为initWebApplicationContext初始化方法把创建的XmlWebApplicationContext 塞到了 currentContextPerThread 中。
而最终产生的WebApplicationContext是专门为web应用准备的,他允许从相对于web根目录的路劲中装载配置文件完成初始化工作,从WebApplicationContext中可以获得ServletContext的引用,整个Web应用上下文对象将作为属性放置在ServletContext中,以便web应用可以访问spring上下文,spring中提供WebApplicationContextUtils的getWebApplicationContext(ServletContext src)方法来获得WebApplicationContext对象。
Part3:SpringMVC的IoC容器的启动
①条件:
②如何连接?
1、DispatcherServle
提供了在web容器中对springMVC的接口,作为SpringMVC处理Web请求的转发器建立起来,从而完成了相应HTTP请求的准备。
③初始化过程
首先:HttpServletBean继承HttpServlet:
其中HttpServlet中的方法:
init()-->将Servlet初始化参数(init-param)设置到该组件上,通过BeanWrapper简化设值过程,方便后续使用;
initServletBean()-->提供给子类初始化扩展点,该方法由FrameworkServlet覆盖。
之后:FrameworkServlet继承HttpServletBean:
initServletBean()进行Web上下文初始化:① 初始化web上下文 ②提供给子类初始化扩展点;结果:基本上如果ContextLoaderListener加载了上下文将作为根上下文(DispatcherServlet的父容器)。
最后调用了onRefresh()方法执行容器的一些初始化,这个方法由子类实现,来进行扩展。
最后:DispatcherServlet继承FrameworkServlet
实现了onRefresh()方法提供一些前端控制器相关的配置:DispatcherServlet启动时会进行我们需要的Web层Bean的配置,如HandlerMapping、HandlerAdapter等,而且如果我们没有配置,还会给我们提供默认的配置。
④结果
从ServletContext中得到根上下文作为DispatcherServlet持有上下文的双亲上下文。
在根上下文基础上,在对自己持有的上下文进行初始化,会建立自己的上下文来持有SPring MVC的bean对象,作为自己持有的IoC容器。
最后把自己持有的这个上下文保存到ServletContext中
Part4:SpringMVC请求分发
①HandlerMapping:
DispatcherServlet启动时会进行我们需要的Web层Bean的配置,如HandlerMapping、HandlerAdapter等,而且如果我们没有配置,还会给我们提供默认的配置。里面存放了一个list放置url与Controller的映射关系.
②使用HandlerMapping完成对请求的映射处理。
③对请求的分发
doService()中完成对http请求的响应。
doDispatcher()完成分发。其中getHandler响应请求,执行Handler得到ModelAndView,交给视图对象呈现。
参考博客:
http://jinnianshilongnian.iteye.com/blog/1602617
https://www.cnblogs.com/09120912zhang/p/7746252.html
https://www.cnblogs.com/xdouby/p/6476750.html
https://blog.youkuaiyun.com/limm33/article/details/51025047
https://blog.youkuaiyun.com/gzu_imis/article/details/18989679
推荐一个公众号,免费领架构师学习资料,每周更新优质文章,能学到很多。