Spring 启动过程分析
启动流程简介
Spring简介
Spring的最基本的功能就是创建对象及管理这些对象之间的依赖关系,实现低耦合,高内聚.还提供像通用日志记录,性能统计,安全控制,异常处理等面向切面的能力.还能帮我们管理最偷偷的数据库事务,本身提供了一套简单的JDBC访问实现,提供与第三方数据库访问框架继承(如Hibernate ,JPA),与各种JavaEE技术整合,如(JavaMail,任务调度等),提供一套自己的web层框架Spring MVC , 而且还能非常简单的与第三方的web框架继承. 从朱磊我们可以认为Spring是一个超级粘合平台,除了自己提供功能之外,还提供粘合其他技术和框架的能力,从而使我们可以更自由的选择到底用什么技术进行开发.而且不管是javaSE/(C/S架构),应用程序还是JavaEE(B/S架构)应用程旭都可以使用这这个平台进行开发.
Spring 运行流程
Spring的启动过程起始就是其容器IOC容器的启动过程,对于WEB程序,IOC容器启动过程即是建立上下问过程.
首先看web.xml中的配置
<servlet> <servlet-name>mvc-dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>mvc-dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
配置文件分析
<!-- 加载Spring配置文件,初始化上下文. --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value> </context-param> <!-- ContextLoaderListener 是一个实现了ServletContextListener接口的监听器 在启动项目时,会触发contextinitialized方法(该方法主要完成ApplicationContext对象的创建),在关闭项目时会触发contextDestroyed方法(该方法会执行ApplicationContext清理操作) --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
这段是加载Spring配置文件,初始化上下文,ContextLoaderListener的initWebApplicationContext方法创建上下文对象.
initWebApplicationContext方法做了但件事情.
序号 事件 1 创建WebApplicationContext对象 2 加载对应的Spring文件创建Bean的实例 3 将WebApplicationContext放入ServletContext(就是Java Web的全局变量) createWebApplicationContext 创建上下文对象,支持用户自定义的上下文对象,但必须继承自ConfigurableWebApplicationContext,而S平均日那个MVC默认使用ConfigurableWebApplicationContext作为Applicationcontext(它仅仅是一个接口)的实现.
configuraAdnRefreshWebApplicationContext方法用于封装Applicationcontext数据并初始化所有相关Bean对象,它会从web.xml中读取contextConfigLocation的配置,这就是spring xml数据源设置,然后放到ApplicationContext , 最后调用传说中的refresh方法执行所有的Java对象的创建.
完成ApplicationContext创建之后就是将其放入ServletContext中,注意它存储的key值常量.
<servlet> <servlet-name>mvc-dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-servlet-config.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>mvc-dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
这段是启动容器初始化DispatcherServlet,web.xml中设置了Servlet的load-on-startup:表示启动容器时初始化该Servlet.
url-pattern:表示哪些请求提交给Spring Web MVC 处理,”/” 是用来定义默认的Servlet映射的,也可以加”*.html”表示拦截所有以html为扩展名的请求.
DispatcherServlet:默认使用WebApplicationcontext(ContextLoaderListener初始化的产生),作为上下文,Spring默认配置文件为”/WEB/INF/(servlet名字)” ,(该名字可以自定义,在<param-value>)
DispatcherServlet 也可以配置自己的初始化参数,覆盖默认配置,因此我们可以通过添加初始化参数.
<servlet> <servlet-name>chapter2</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-servlet-config.xml</param-value> </init-param> </servlet>
如果使用如上配置,Spring Web MVC框架将加载”classpath:spring-servlet-config.xm”来进行初始化上下文,而不是/WEB-INF/[servlet名字]-servlet.xml
DispatcherServlet初始化顺序:
HttpServletBean继承HttpServlet,因此Web容器启动时,将调用它的init方法,初始化方法的主要作用:将Servlet初始化参数(init-param) 设置到该组件上(如contextAttribute,contextClass,namespace,ContextConfigLocation)通过BeanWrapper简化设值过程,方便后续使用;提供给子类初始化扩展点,initServletBean(),该方法由FramewworkServlet覆盖.
FrameworkServlet继承HttpServletBean,通过initServletBean()进行Web上下文访问,该方法主要覆盖下两件事情,①初始化web②提供子类初始化扩展点.
DispatcherServlet继承FrameworkServlet ,并实现了onRefresh() 方法 提供一些前端控制器相关配置
整个DispatcherServlet初始化过程做了如下事情
- 初始化Spring Web MVC使用Web上下文 ,并且指定父容器WebApplicationcontext(ContextLoaderListener加载了的根上下文);
- 初始化DispatcherServlet使用策略,如HandlerMapping,handlerAdapter等.
总体概括Spring启动流程
- 首先,对于一个web应用,其部署在web容器中,web容器提供一个全局的上下文环境,这个上下文就是ServletContext,其为后面的Spring IOC容器提供环境.
- 其次,在web.xml中提供有contextLoaderListener.在web容器启动时,会触发容器初始化事件,此时,contextLoaderListener会监听到这个事件,其contextInitialized方法会被调用,在这个方法中,spring会初始化一个启动上下文,这个上下文被称为根上下文,即WebApplicationcontext,这是一个接口类,确切的说,其实实际的实现类是XmlWebApplicationContext.这个就是spring的IOC容器.其对应的Bean定义的配置由web.xml中的context-param标签.在这个IOC容器初始化完毕后,spring以WebApplicationContext.ROOT*WEB*APPLICATION*CONTEXT*ATTRIBUTE为属性Key,将其存储到ServletContext中,便于获取.
- 再次,contextLoaderListener监听器初始化完毕后,开始初始化web.xml中配置Servlet,这里是DispatcherServlet,这个servlet实际上是一个标准的前端控制器,用以转发,匹配,处理每个servlet请求.DispatcherServlet上下文在初始化的时候会建立自己的IOC上下文,用以支持SpringMVC相关的bean.在建立DispatcherServlet自己的IOC容器上下文时,会利用WebApplicationcontext.ROOTWEBAPPLICATIONCONTEXTAPTTRIBUTE先从ServletContext中获取之前的根上下文(即WebApplicationcontext)作为上下文的parent上下文,有了这个parent上下文之后,再初始化自己持有的上下文.这个DispatcherServlet初始化自己上下文的工作在器initStrategies方法中可以看到,大概的工作就是初始化处理器映射,视图解析等.这个servlet自己持有的上下文默认事先类也是mlWebApplicationcontext.初始化完毕后,Spring以与servlet的名字持有的上下文默认实现类是mlWebApplicationcontext.初始化完毕后,spring以与serve聊天的名字相关(此处不是以servlet名为Key,而是通过一些转换,具体可以自行查看源码)的属性为key属性,也将其存到ServletContext 中,以便后续使用.这样每个servlet就持有自己的上下文,即拥有自己独立的bean空间,同时各个servlet共享相同的bean,即根上下文定义的哪些bean.