在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加载过程的更多相关文章

  1. 深入理解 spring 容器,源码分析加载过程

    Spring框架提供了构建Web应用程序的全功能MVC模块,叫Spring MVC,通过Spring Core+Spring MVC即可搭建一套稳定的Java Web项目.本文通过Spring MVC ...

  2. web.xml加载过程

    web.xml加载过程:1 启动WEB项目的时候,容器(如:Tomcat)会读他的配置文件web.xml读两个节点  <listener></listener>和<con ...

  3. springmvc源码分析——入门看springmvc的加载过程

    本文将分析springmvc是如何在容器启动的时候将各个模块加载完成容器的创建的. 我知道在web.xml文件中我们是这样配置springmvc的: 可以看到,springmvc的核心控制器就是Dis ...

  4. web.xml的加载过程配置详解

      一:web.xml加载过程 简单说一下,web.xml的加载过程.当我们启动一个WEB项目容器时,容器包括(JBoss,Tomcat等).首先会去读取web.xml配置文件里的配置,当这一步骤没有 ...

  5. java web.xml被文件加载过程及加载顺序小结

    web.xml加载过程(步骤): 1.启动WEB项目的时候,容器(如:Tomcat)会去读它的配置文件web.xml.读两个节点: <listener></listener> ...

  6. Java web 加载过程

    1.Web容器初始化过程 2.SpringMVC中web.xml配置 3.认识ServletContextListener 4.认识ContextLoaderListener 5.Dispatcher ...

  7. Java Web应用的加载过程

    在介绍Spring IoC和MVC的加载前,用这篇小文章简单地记录下,最简单的web应用的加载过程. 一.从最简单的web应用出发 使用Eclipse直接创建一个Dynamic Web Project ...

  8. web.xml被文件加载过程,各节点加载顺序总结

    web.xml被文件加载过程,各节点加载顺序总结 博客分类: J2EE WebXMLSpringServletBean  今天2010-3-11日,上班无事,想来将web.xml项目描述文件的加载过程 ...

  9. 工厂模式模拟Spring的bean加载过程

    一.前言    在日常的开发过程,经常使用或碰到的设计模式有代理.工厂.单例.反射模式等等.下面就对工厂模式模拟spring的bean加载过程进行解析,如果对工厂模式不熟悉的,具体可以先去学习一下工厂 ...

随机推荐

  1. 51Nod 1091 线段的重叠(贪心+区间相关,板子题)

    1091 线段的重叠 基准时间限制:1 秒 空间限制:131072 KB 分值: 5         难度:1级算法题 X轴上有N条线段,每条线段包括1个起点和终点.线段的重叠是这样来算的,[10 2 ...

  2. HDU2063-过山车-匈牙利算法

    过山车 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...

  3. stl 在 acm中的应用总结

    总结一些在acm中常用的小技巧,小函数 之前尝试着总结过很多次.都失败了,因为总是担心不全,理解的也不是很透彻.这次再来一次...其实之前保存了很多的草稿就不发布了,当然,下面说的很不全面,路过的大牛 ...

  4. You can Solve a Geometry Problem too(线段求交)

    http://acm.hdu.edu.cn/showproblem.php?pid=1086 You can Solve a Geometry Problem too Time Limit: 2000 ...

  5. c# excel 导入 与 导出(可直接用)

    c#操作excel方式很多 采用OleDB读取EXCEL文件: 引用的com组件:Microsoft.Office.Interop.Excel.dll   读取EXCEL文件 将EXCEL文件转化成C ...

  6. 布隆(Bloom)过滤器 JAVA实现

    前言 Bloom过滤器,通过将字符串映射为信息指纹从而节省了空间.Bloom过滤器的原理为,将一个字符串通过一定算法映射为八个Hash值,将八个Hash值对应位置的Bitset位进行填充.在进行校验的 ...

  7. C++ enum用法小技巧

    enum DeviceDataType :int    {        None = 0,              SourceRGBA32 = 1,               Keying = ...

  8. 10年java过来人聊聊自己的自学、培训和工作经历

    一 . 自我介绍 我叫王涛,我是一位北漂十年的码农,2008年9月份开始自学java,三个月后,自学无果,于2008年11月份开始参加培训,培训完之后,我觉得自己还是啥也不会,只会抄抄代码,竟然连de ...

  9. Web前端性能优化——如何提高页面加载速度

    前言:  在同样的网络环境下,两个同样能满足你的需求的网站,一个"Duang"的一下就加载出来了,一个纠结了半天才出来,你会选择哪个?研究表明:用户最满意的打开网页时间是2-5秒, ...

  10. Node.js进阶:5分钟入门非对称加密方法

    前言 刚回答了SegmentFault上一个兄弟提的问题<非对称解密出错>.这个属于Node.js在安全上的应用,遇到同样问题的人应该不少,基于回答的问题,这里简单总结下. 非对称加密的理 ...