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加载过程进行解析,如果对工厂模式不熟悉的,具体可以先去学习一下工厂 ...
随机推荐
- COGS 68. [NOIP2005] 采药【01背包复习】
68. [NOIP2005] 采药 ★ 输入文件:medic.in 输出文件:medic.out 简单对比 时间限制:1 s 内存限制:128 MB [问题描述] 辰辰是个天资聪颖的孩 ...
- C语言缓冲区(缓存)详解
缓冲区又称为缓存,它是内存空间的一部分.也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区.缓冲区根据其对应的是输入设备还是输出设备,分为输 ...
- zookeeper基本讲解及基本命令和配置 (转)
一.ZooKeeper概述 ZooKeeper是一种为分布式应用所设计的高可用.高性能且一致的开源协调服务,是Google的Chubby一个开源实现,是Hadoop和Hbase的重要组件,它提供了一项 ...
- 启动时候报错由于没有扫包 error creating bean with name
<!-- 扫描包,加载service实现类 --> <context:component-scan base-package="com.taotao.search.serv ...
- [学习OpenCV攻略][010][写入AVI文件]
cvSize(文件宽度,文件高度) 通过图片或视频文件的宽高得到尺寸信息,返回值是CvSize cvCreateVideoWriter(输出文件名,编码格式,帧率,图像大小) 通过设置输出视频的格式信 ...
- log4j配置文件简要记录
和大多数配置文件一样,log4j配置文件也有key-value形式和xml形式.这里主要记录一下key-value的形式 我们通过配置,可以创建出Log4j的运行环境.Log4j由三个重要的组件构成: ...
- SQL Constraints
每个表可以有多个 UNIQUE 约束,但是每个表只能有一个 PRIMARY KEY 约束. http://www.w3school.com.cn/sql/sql_unique.asp 另外相关:@On ...
- iptables nat及端口映射
iptables nat及端口映射 发布: 2010-6-11 15:05 | 作者: admin | 来源: SF NetWork 门户网站 iptables 应用初探(nat+三层访问控制) ip ...
- linux下建ftp用户,并限制用户访问路径[转]
目的是:在linux系统上建立ftp用户,并限制其通过ftp访问时,只能访问用户主目录:其主目录显示路径也是“/”,看不到上级目录. 例如,我要建立用户usertest,密码为usertest ...
- oracle 查看最大连接数与当前连接数
select count(*) from v$process --当前的连接数 select value from v$parameter where name = 'processes' --数据库 ...