Spring框架学习[Web环境中Spring的启动过程](五)
2014-11-24 03:05:48
·
作者:
·
浏览: 5
ation 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上下文实现类的无参构造方法创建实例对象 ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass); //如果Servlet大版本是2,并且小版本号小于5,即是Servlet2.4以下标准 if (sc.getMajorVersion() == 2 && sc.getMinorVersion() < 5) { //获取Servlet上下文名称 String servletContextName = sc.getServletContextName(); //为创建的Web应用上下文设置唯一的Id标识 wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(servletContextName)); } //Servlet2.5标准 else { try { //调用Servlet上下文对象中getContextPath()方法 String contextPath = (String) ServletContext.class.getMethod("getContextPath").invoke(sc); //为Web上下文设置唯一Id标识 wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(contextPath)); } catch (Exception ex) { throw new IllegalStateException("Failed to invoke Servlet 2.5 getContextPath method", ex); } } //设置Web上下文的父级上下文 wac.setParent(parent); //设置Web上下文的Servlet上下文 wac.setServletContext(sc); //Servlet上下文从web.xml文件中获取配置的contextConfigLocation参数,并//将其作为Spring Web上下文配置资源的值 wac.setConfigLocation(sc.getInitParameter(CONFIG_LOCATION_PARAM)); //调用用户自定义的设置应用上下文方法 customizeContext(sc, wac); //刷新Spring Web容器,启动载入Spring配置资源的过程 wac.refresh(); return wac; }//根据给定的Servlet上下文,获取Spring Web上下文的实现类//XmlWebApplicationContext或者用户自定义的Spring Web应用上下文protected Class< > determineContextClass(ServletContext servletContext) { //Servlet上下文从web.xml中获取配置的contextClass参数值 String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM); //如果web.xml中额外配置了contextClass参数值 if (contextClassName != null) { try { //使用JDK反射机制,实例化指定名称的contextClass类对象 return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader()); } catch (ClassNotFoundException ex) { throw new ApplicationContextException( "Failed to load custom context class [" + contextClassName + "]", ex); } } //如果web.xml中没有配置contextClass参数值 else { //获取Spring中默认的Web应用上下文策略,即XmlWebApplicationContext contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName()); try { //使用JDK反射机制,创建Spring Web应用上下文默认策略类对象 return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader()); } catch (ClassNotFoundException ex) { throw new ApplicationContextException( "Failed to load default context class [" + contextClassName + "]", ex); } } }
通过上面ContextLoader初始化Spring Web上下文的主要源码分析,我们看到当Web应用在Web服务器启动时,Servlet上下文通过web.xml文件获取所配置的contextConfigLocation、contextClass等参数,定位Spring配置文件资源,调用Spring Web容器的刷新的refresh()方法启动Web环境中Spring Ioc容器的初始化过程,refresh()方法启动Spring IoC容器的初始化过程我们在IoC容器源码分析中已经分析过,这里不再重述。
(2). ContextLoader关闭Spring Web上下文的主要源码:
[java] view plaincopyprint //关闭指定Servlet上下文中的Spring Web应用上下文 public void closeWebApplicationContext(ServletContext servletContext) { servletContext.log("Closing Spring root WebApplicationContext"); try { //Spring Web应用上下文的类型都是ConfigurableWebApplicationContext if (this.context instanceof ConfigurableWebApplicationContext) { //关闭Spring Web应用上下文,释放资源,销毁所有缓存的单态模式Bean ((ConfigurableWebApplicationContext) this.context).close(); } } finally { //获取当前线程的上下文类加载器 ClassLoader ccl = Thread.currentThread().getContextClassLoader(); //将当前上下文对象设置为null if (ccl ==