ContextLoaderListener加载过程
在web.xml中,配置ContextLoaderListener
<!-- 配置Listener,用来创建Spring容器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener> <context-param>
<!-- 配置Listener参数:告诉它Spring的配置文件位置,它好去创建容器 -->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:application-context*.xml</param-value>
</context-param>
说明:<listener>标签中,ContextLoaderListener用来创建Spring容器;而<context-param>标签,用来指定了spring配置文件的位置,该两个标签共同起作用,也就可以在web项目启动后,成功的创建了Spring容器了。
分析如下:
1.ContextLoaderListener实现了ServletContextListener接口,ServletContextListener是Java EE标准接口之一,类似tomcat,jetty的java容器启动时便会触发该接口的contextInitialized。也就是说会激活调用ContextLoaderListener的contextInitialized()方法
2.ContextLoaderListener类中的contextInitialized方法如下
/**
* Initialize the root web application context.
*/
@Override
public void contextInitialized(ServletContextEvent event) {
initWebApplicationContext(event.getServletContext());
}
3.我们在进入到ClassLoader类的initWebApplicationContext( )方法内部,会注入ServletContext servletContext的参数对象,同时帮我们返回一个WebApplicationContext容器对象,代码如下:
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) { /** 此处省略部分代码 */ 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 { if (this.context == null) {
/**
* 重要,该方法会帮我们创建WebApplicationConntext,并赋值给ContextLoaderListener类的context对象。
* 说明:ContextLoaderListener类的context属性来自于它的父类
*/
this.context = createWebApplicationContext(servletContext);
}
if (this.context instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
if (!cwac.isActive()) { /** 此处省略部分代码 */ 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;
} /** 此处省略部分代码 */ return this.context;
} }
debug打断点我们可以看到注入ServletContext servletContext的参数对象,是ApplicationContextFacade类型的对象,内部是通过Map来实现的,用来加载Spring的配置文件。
也就是说,该方法执行完后,我们就会拿到WebApplicationContext类型的Spring容器对象。那么该方法内部具体是如何加载Spring配置文件的呢,是如何创建WebApplicationContext对象?我们接着往下看
4.我们可以看到该行代码:this.context = createWebApplicationContext(servletContext); 该方法用于创建WebApplicationContext对象,并赋值给context属性。WebApplicationContext是一个接口类,本质上返回的是XmlWebApplicationContext,它就是Spring容器了
5.我们再进入到createWebApplicationContext(servletContext)方法中:
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);
}
会将刚才注入的ApplicationContextFacade对象传入,用于指定Spring的配置文件位置,它的内部是通过Map来实现的,也就是说,该类会解析<context-param>标签的内容,加载Spring配置文件,有了配置文件就可以初始化容器了
6.createWebApplicationContext( ) 调用determineContextClass( )方法
determineContextClass有如下代码:
contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
7.很明显是从defaultStrategies中加载的
ContextLoader 类中有段静态代码:会加载默认配置,也就是会加载<param-value>classpath:application-context*.xml</param-value>中的xml文件
static {
try {
ClassPathResource resource = new ClassPathResource("ContextLoader.properties", ContextLoader.class);
defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
}
catch (IOException ex) {
throw new IllegalStateException("Could not load 'ContextLoader.properties': " + ex.getMessage());
}
}
8.ContextLoader.properties 文件内容如下:
org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext
此时,determineContextClass( )方法返回的是XmlWebApplicationContext对象,之后回到3步骤中的configureAndRefreshWebApplicationContext( )方法
9. configureAndRefreshWebApplicationContext的细节调用
configureAndRefreshWebApplicationContext 调用了AbstractApplicationContext的refresh方法
refresh 方法调用了obtainFreshBeanFactory
obtainFreshBeanFactory 调用了AbstractRefreshableApplicationContext类的refreshBeanFactory方法
refreshBeanFactory调用了XmlWebApplicationContext的loadBeanDefinitions
loadBeanDefinitions中加载了对应的applicationContext.xml
ContextLoaderListener加载过程的更多相关文章
- 深入理解 spring 容器,源码分析加载过程
Spring框架提供了构建Web应用程序的全功能MVC模块,叫Spring MVC,通过Spring Core+Spring MVC即可搭建一套稳定的Java Web项目.本文通过Spring MVC ...
- web.xml加载过程
web.xml加载过程:1 启动WEB项目的时候,容器(如:Tomcat)会读他的配置文件web.xml读两个节点 <listener></listener>和<con ...
- springmvc源码分析——入门看springmvc的加载过程
本文将分析springmvc是如何在容器启动的时候将各个模块加载完成容器的创建的. 我知道在web.xml文件中我们是这样配置springmvc的: 可以看到,springmvc的核心控制器就是Dis ...
- web.xml的加载过程配置详解
一:web.xml加载过程 简单说一下,web.xml的加载过程.当我们启动一个WEB项目容器时,容器包括(JBoss,Tomcat等).首先会去读取web.xml配置文件里的配置,当这一步骤没有 ...
- java web.xml被文件加载过程及加载顺序小结
web.xml加载过程(步骤): 1.启动WEB项目的时候,容器(如:Tomcat)会去读它的配置文件web.xml.读两个节点: <listener></listener> ...
- Java web 加载过程
1.Web容器初始化过程 2.SpringMVC中web.xml配置 3.认识ServletContextListener 4.认识ContextLoaderListener 5.Dispatcher ...
- Java Web应用的加载过程
在介绍Spring IoC和MVC的加载前,用这篇小文章简单地记录下,最简单的web应用的加载过程. 一.从最简单的web应用出发 使用Eclipse直接创建一个Dynamic Web Project ...
- web.xml被文件加载过程,各节点加载顺序总结
web.xml被文件加载过程,各节点加载顺序总结 博客分类: J2EE WebXMLSpringServletBean 今天2010-3-11日,上班无事,想来将web.xml项目描述文件的加载过程 ...
- 工厂模式模拟Spring的bean加载过程
一.前言 在日常的开发过程,经常使用或碰到的设计模式有代理.工厂.单例.反射模式等等.下面就对工厂模式模拟spring的bean加载过程进行解析,如果对工厂模式不熟悉的,具体可以先去学习一下工厂 ...
随机推荐
- HDU1097-A hard puzzle-快速幂+取模
快速幂: 代码: kuaisumi(ll a,ll b){ ll ans=; while(b){ ==){ ans=ans*a; ...
- HDU2973(威尔逊定理)
YAPTCHA Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total S ...
- HDU_5523Game
Game Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Total Sub ...
- Kibana使用高德地图
Kibana使用高德地图 说明 目前Kibana默认自带的地图全部是英文,更换高德地图对地图汉化 修改配置 1.编辑kibana配置文件kibana.yml,最后面添加 tilemap.url: 'h ...
- c语言基础学习09_复合类型
=============================================================================涉及到的知识点有:一.结构体1.定义结构体st ...
- insertBefore方法(javascript与jQuery)
说到insertBefore()方法,其实javascript与jQuery中都有此方法,那么他们用法是否相同呢? 其实,还是有点区别的.反正我是爱搞混淆了,先做个小笔记吧! 1.insertBefo ...
- JavaScrip 排序算法
转自: http://blog.givebest.cn/javascript/2017/08/02/javascript-sorting-algorithms.html 基础构造函数 以下几种排序算法 ...
- git上传项目全部流程
一.下载git 进入网址:https://git-scm.com/downloads: 点击中的Download 2.16.0 for Windows; 在中选择蓝色字段点击,根据电脑64或32位选择 ...
- Dos下的小技巧
1.dos 窗口下怎样复制粘贴 第一种方式:右键标记-->选中-->标题栏右键编辑-->复制 第二种方式:右键-->标记-->选中-->enter 这样就可以复制了 ...
- 微调数据库表结构,30 分钟搞定 WordPress 数据库查询缓慢问题
同事的美女图片站,基于 WordPress 搭建的,因为数据越来越多,变得慢,我从 PHP slow log 里面看出是 WordPress 有些查询总是很慢,即使已经安装了页面缓存插件,但是由于页面 ...