基于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 分属于不同的可见范围。