springmvc源码之Web上下文初始化
web上下文与SerlvetContext的生命周期应该是相同的,springmvc中的web上下文初始化是由ContextLoaderListener来启动的

在web.xml中配置ContextLoaderListener
org.springframework.web.context.ContextLoaderListener
contextConfigLocation classpath:applicationContext.xml
ContextLoaderListener实现了ServletContextListener接口,ServletContextListener是Servlet定义的,提供了与Servlet生命周期结合的回调,contextInitialized方法和contextDestroyed方法;ContextLoaderListener继承了ContextLoader类,通过ContextLoader来完成实际的WebApplicationContext的初始化工作,并将WebApplicationContext存放至ServletContext中,ContextLoader就像是spring应用在web容器中的启动器
从spring3.x起就不需要配置监听器ContextLoaderListener,只需要配置DispatcherServlet就可以了
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {/*** Initialize the root web application context.*/// ServletContext被创建时触发,初始化web上下文@Overridepublic void contextInitialized(ServletContextEvent event) {initWebApplicationContext(event.getServletContext());}/*** Close the root web application context.*/// ServletContext被销毁时触发,关闭web上下文@Overridepublic void contextDestroyed(ServletContextEvent event) {closeWebApplicationContext(event.getServletContext());ContextCleanupListener.cleanupAttributes(event.getServletContext());}}
在启动时会创建一个WebApplicationContext作为IOC容器,默认的实现类是XmlWebApplicationContext
/** Default config location for the root context */
// 默认的配置位置,如果不进行配置,就会读取这个文件
public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml";/** Default prefix for building a config location for a namespace */
// 配置文件默认在/WEB-INF/目录下
public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/";/** Default suffix for building a config location for a namespace */
// 配置文件默认后缀名是.xml
public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml";
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {// WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE是WebApplicationContext.class.getName() + ".ROOT"// 如果servletContext中已经存在根上下文属性,则说明已经有一个根上下文存在了if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {throw new IllegalStateException("Cannot initialize context because there is already a root application context present - " +"check whether you have multiple ContextLoader* definitions in your web.xml!");}Log logger = LogFactory.getLog(ContextLoader.class);servletContext.log("Initializing Spring root WebApplicationContext");long startTime = System.currentTimeMillis();try {// Store context in local instance variable, to guarantee that// it is available on ServletContext shutdown.if (this.context == null) {// 初始化contextthis.context = createWebApplicationContext(servletContext);}if (this.context instanceof ConfigurableWebApplicationContext) {ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;if (!cwac.isActive()) {// The context has not yet been refreshed -> provide services such as// setting the parent context, setting the application context id, etcif (cwac.getParent() == null) {// The context instance was injected without an explicit parent ->// determine parent for root web application context, if any.ApplicationContext parent = loadParentContext(servletContext);cwac.setParent(parent);}configureAndRefreshWebApplicationContext(cwac, servletContext);}}// 记录在servletContext中servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);ClassLoader ccl = Thread.currentThread().getContextClassLoader();if (ccl == ContextLoader.class.getClassLoader()) {currentContext = this.context;}else if (ccl != null) {currentContextPerThread.put(ccl, this.context);}return this.context;}catch (RuntimeException ex) {logger.error("Context initialization failed", ex);servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);throw ex;}catch (Error err) {logger.error("Context initialization failed", err);servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err);throw err;}
}
protected WebApplicationContext createWebApplicationContext(ServletContext sc) {// 如果在web.xml中有配置contextClass,则使用配置的类// 如果没有配置,则使用默认的配置 ContextLoader.properties// org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContextClass> contextClass = determineContextClass(sc);if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {throw new ApplicationContextException("Custom context class [" + contextClass.getName() +"] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");}return (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
}
下一篇:模模糊糊的反义词是什么标准答案