深入分析ContextLoaderListener
来源:互联网 发布:软件的缺陷等级 编辑:程序博客网 时间:2024/06/05 03:57
本篇参考了【spring源码解析】,在此基础加ru个人理解。适合刚开始学习spring(mvc)的开发人员。
本人头一次写博客,如有不对或者不好的地方欢迎大家指正,让我们一起进步,为了money!!!
1. ContextLoaderListener简介
它的作用是启动web应用服务器时,自动装配ApplicationContext的配置信息。它实现了ServletContextListener
public class ContextLoaderListener extends ContextLoader implements ServletContextListener
在web.xml中配置监听器,启动容器时就会执行实现的方法。使用ServletContextListener接口,开发者能够在请求前向ServletContext中添加任意的对象。ServletContext在服务启动时初始化,在整个运行期间都是可见的,生命周期与应用的周期一致。
2. ContextLoaderListener源码分析
ContextLoaderListener实现了ServletContextListener接口
public interface ServletContextListener extends EventListener { void contextInitialized(ServletContextEvent var1); void contextDestroyed(ServletContextEvent var1);}
ServletContextListener有2个方法,contextInitialized是在应用服务器启动时执行,contextDestroyed是在应用服务器销毁时执行。
ContextLoaderListener即重写了ServletContextListener的方法
/*** 应用容器启动时执行*/@Overridepublic void contextInitialized(ServletContextEvent event) { /** * spring环境启动方法 */ initWebApplicationContext(event.getServletContext());}/*** 应用容器销毁时执行*/@Overridepublic void contextDestroyed(ServletContextEvent event) { closeWebApplicationContext(event.getServletContext()); ContextCleanupListener.cleanupAttributes(event.getServletContext());}
initWebApplicationContext方法完成了spring的初始化,其中event.getServletContext()即上文提到的ServletContext对象,ServletContext其中有2个方法
Object getAttribute(String var1);void setAttribute(String var1, Object var2);
我们可以在整个应用生命周期内通过ServletContext添加或获取自定义的对象。
我们继续看initWebApplicationContext方法做了什么工作,首先看源码
public WebApplicationContext initWebApplicationContext(ServletContext 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"); if (logger.isInfoEnabled()) { logger.info("Root WebApplicationContext: initialization started"); } long startTime = System.currentTimeMillis(); try { // Store context in local instance variable, to guarantee that // it is available on ServletContext shutdown. if (this.context == null) { this.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, etc if (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.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); } 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"); } 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; } }
initWebApplicationContext方法主要是创建了WebApplicationContext实例的一个功能框架,大致分为以下步骤
2.1 WebApplicationContext存在性验证。
在web.xml中只允许声明一次ContextLoaderListener。在spring中创建的WebApplicationContext实例会保存在ServletContext中以方便全局调用,key为 WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE。
2.2 WebApplicationContext实例创建
protected WebApplicationContext createWebApplicationContext(ServletContext sc) { Class<?> 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); }
首先获取实现WebApplicationContext的context class类,该contextClass可以在web.xml指定,也可以默认为ContextLoader.properties中的XmlWebApplicationContext
通过BeanUtils实例化该类
2.3 刷新上下文环境,进行配置文件的加载 configureAndRefreshWebApplicationContext 请参考ContextLoader源码
2.4 将实例保存到ServletContext中
2.5 映射当前的类加载器与webApplicationContext实例到全局变量currentContextPerThread
3.ContextLoaderListener在应用容器中使用
3.1 在web.xml中增加全局参数,指定spring 加载配置文件的路径
<context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/classes/applicationContext-*.xml </param-value> </context-param>
如果不指定,默认的路径是/WEB-INF/applicationContext.xml,参考XmlWebApplicationContext.DEFAULT_CONFIG_LOCATION
3.2 web.xml中增加ContextLoaderListener过滤器
<listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class></listener>
这样我们就完成了spring环境的启动
下一篇我们将分析下DispatcherServlet
1 0
- 深入分析ContextLoaderListener
- Spring ContextLoaderListener源码分析
- Spring ContextLoaderListener源码分析 .
- springMVC之ContextLoaderListener分析
- Spring ContextLoaderListener源码分析 .
- WebApplicationContext初始化及ContextLoaderListener分析
- ContextLoaderListener
- ContextLoaderListener
- ContextLoaderListener
- ContextLoaderListener
- ContextLoaderListener
- ContextLoaderListener
- ContextLoaderListener
- ContextLoaderListener
- ContextLoaderListener
- ContextLoaderListener
- 第九篇 sping深入学习之ContextLoaderListener与ContextLoaderServlet
- 【spring】源码分析 <一> 从ContextLoaderListener开始·
- Groovy入门学习
- 算法基础概念
- iOS集成极光之后,提交审核IDFA配置
- 数据库 VS 数据仓库
- 线性查找法&二分查找法
- 深入分析ContextLoaderListener
- 一、步进电机的结构及原理
- C#事务处理(三)之Transactions事务
- 滑动切换Activity
- Android 蓝牙总结
- HashSet和TreeSet的区别
- 使用html5 audio api音频可视化: Hello by OMFG
- iOS多线程理解告别生硬
- 2016数据库技术盘点