3.ContextLoader初始化和销毁Spring Web上下文:
(1).ContextLoader初始化Spring Web上下文的主要源码如下:
[java] view plaincopyprint //初始化Spring根上下文 public WebApplicationContext initWebApplicationContext(ServletContext servletContext) { //ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT"; //判断在Servlet上下文中Spring Web应用给根上下文是否已经存在 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"); if (logger.isInfoEnabled()) { logger.info("Root WebApplicationContext: initialization started"); } //获取当前 系统时间 long startTime = System.currentTimeMillis(); try { //如果当前Web根容器有父容器,则获取父容器 ApplicationContext parent = loadParentContext(servletContext); //根据给定Servlet容器和父容器创建Web应用容器,并且所创建的Web应用 //容器实例对象存储在本地变量中,以确保当Servlet容器关闭时该容器可用 this.context = createWebApplicationContext(servletContext, parent); //将创建的Web应用上下文设置到Servlet上下文的应用根容器属性中 servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context); //获取当前线程的容器类加载器 ClassLoader ccl = Thread.currentThread().getContextClassLoader(); //如果当前线程的容器类加载器是ContextLoader类,则当前上下文就设置为 //创建的Web应用上下文 if (ccl == ContextLoader.class.getClassLoader()) { currentContext = this.context; } //如果当前线程的容器类加载器不为null,则将创建的web应用上下文和其类 //加载器缓存在容器类加载器—>Web应用上下文Map集合中 else if (ccl != null) { currentContextPerThread.put(ccl, this.context); } if (logger.isDebugEnabled()) { logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" + WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]"); } if (logger.isInfoEnabled()) { long elapsedTime = System.currentTimeMillis() - startTime; logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms"); } //返回创建的Web应用上下文 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; } } //创建Web应用上下文 protected WebApplicationContext createWebApplicationContext(ServletContext sc, ApplicationContext parent) { //获取当前Servlet上下文接口的实现类 Class contextClass = determineContextClass(sc); //判断使用什么样的的类在Web容器中作为IoC容器 if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) { throw new ApplicationContextException("Custom context class [" + contextClass.getName() + "] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]"); } //Servlet上下文实现类是ConfigurableWebApplicationContext类型, //使用JDK反射机制,调用Servlet上下文实现类