基于springmvc的web应用初始化流程和配置加载注意点
基于springmvc的web应用在初始化时做了什么?application context何时加载?有几种加载方式?
和所有的java web框架一样,springmvc实际上就是在典型的servlet处理request的流程上再包裹了一层而已。springmvc的初始化流程也同样和容器初始化servlet流程一样。容器初始化servlet上下文的流程如下,servlet context一般而言就是那个web.xml里设定上下文环境。
springmvc中最典型的ServletContextListener实现就是ContextLoaderListener,其重写的contextInitialized方法
定义了spring在初始化servletContext时的一些动作。
其会加载由context-param参数contextConfigLocation中指定的spring
application context配置文件。
配置如下:
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>
- /WEB-INF/applicationContext.xml /WEB-INF/applicationContext2.xml
- </param-value>
- </context-param>
使用
contextConfigLocation 加载指定路径的配置文件时,多个配置文件可以用逗号,冒号,空格,
\t,\n 中任一个来分隔。
如果没有指定contextConfigLocation
参数,ContextLoaderListener会默认加载/WEB-INF/applicationContext.xml这个配置文件。
springmvc将由ContextLoaderListener
载入的application context 叫做 "root application
context" ,以区别于servlet的application
context。
ServletContextListener在servlet context里的配置参考如下:
- <listener>
- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
- </listener>
如果没有在servlet
context里配置,就不存在"root application context"。
springmvc可以配置多个servlet,每一个
servlet都拥有各自的application context,相互之间不能相互访问。但是"root application
context"却是对所有servlet都是可见的。
如果servlet直接使用DispatcherServlet,其application
context在DispatcherServlet的init 方法被调用时初始化。
servlet application
context的加载策略类似于root application context,首先会查找是否配置了servlet的init-param
"contextConfigLocation",如果有,就使用 contextConfigLocation
指定的路径加载的配置文件时,多个配置文件可以用逗号,冒号,空格,
\t,\n 中任一个来分隔。
如果没有指定"contextConfigLocation"参数,则会在
/WEB-INF/下查找 "servlet-name"+"-servlet.xml" 这样的文件加载。如下配置所示,就是/WEB-INF/springDispatcherServlet-servlet.xml 。
- <servlet>
- <servlet-name>springDispatcherServlet</servlet-name>
- <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
- <init-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>
- /WEB-INF/servlet-applicationContext.xml
- </param-value>
- </init-param>
- <load-on-startup>1</load-on-startup>
- </servlet>
- <servlet-mapping>
- <servlet-name>springDispatcherServlet</servlet-name>
- <url-pattern>/mvc/*</url-pattern>
- </servlet-mapping>
最后,该servlet
application context将root application
context设置为parent,然后加载完成。
以后在应用里调用applicationContext或者beanFactory的getBean方法去获取实例的时候,都是先尝试从父级application
context获取,获取不到,再到当前application
context里获取。
除此之外,我们还可以在某个类里以编程式加载application
context,比如使用ClassPathXmlApplicationContext或FileSystemXmlApplicationContext。不过这样加载的application
context和root application context和servlet application context
分属于不同的可见范围。