ContextLoaderListener作用详解
参考网址:http://blog.csdn.net/ysughw/article/details/8992322
ContextLoaderListener监听器的作用就是启动Web容器时,自动装配ApplicationContext的配置信息。因为它实现了ServletContextListener这个接口,在web.xml配置这个监听器,启动容器时,就会默认执行它实现的方法。至于ApplicationContext.xml这个配置文件部署在哪,如何配置多个xml文件,现在的方法就是查看它的API文档。在ContextLoaderListener中关联了ContextLoader这个类,所以整个加载配置过程由ContextLoader来完成。看看它的API说明。
类ContextLoader api原文:
Performs the actual initialization work for the root application context. Called by ContextLoaderListener
.
Looks for a "contextClass"
parameter at the web.xml
context-param level to specify the context class type, falling back to the default of XmlWebApplicationContext
if not found. With the default ContextLoader implementation, any context class specified needs to implement the ConfigurableWebApplicationContext interface.
Processes a "contextConfigLocation"
context-param and passes its value to the context instance, parsing it into potentially multiple file paths which can be separated by any number of commas and spaces, e.g. "WEB-INF/applicationContext1.xml, WEB-INF/applicationContext2.xml". Ant-style path patterns are supported as well, e.g. "WEB-INF/*Context.xml,WEB-INF/spring*.xml" or "WEB-INF/**/*Context.xml". If not explicitly specified, the context implementation is supposed to use a default location (with XmlWebApplicationContext: "/WEB-INF/applicationContext.xml").
第一段说明ContextLoader的作用--它为初始化工作装配请求上下文,这是由于调用ContextLoaderListener触发的。
第二段,ContextLoader将在web.xml寻找contextClass参数,它是上下文的class类型,默认的是
XmlWebApplicationContext。
第三段,讲如何部署applicationContext的xml文件。
如果在web.xml中不写任何参数配置信息,默认的路径是/WEB-INF/applicationContext.xml,在WEB-INF目录下创建的xml文件的名称必须是applicationContext.xml;
如果是要自定义文件名可以在web.xml里加入contextConfigLocation这个context参数:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/classes/applicationContext-*.xml
</param-value>
</context-param>
在<param-value> </param-value>里指定相应的xml文件名,如果有多个xml文件,可以写在一起并一“,”号分隔。上面的applicationContext-*.xml采用通配符,比如这那个目录下有applicationContext-ibatis-base.xml,applicationContext-action.xml,applicationContext-ibatis-dao.xml等文件,都会一同被载入。
相应源码:
在类ContextLoader中的声明:
public static final String CONFIG_LOCATION_PARAM = "contextConfigLocation";
由于ContextLoader的默认上下文是XmlWebApplicationContext,在XmlWebApplicationContext中的声明:
public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml";
由此可见applicationContext.xml的文件位置就可以有两种默认实现:
第一种:直接将之放到/WEB-INF下,之在web.xml中声明一个listener;
第二种:将之放到classpath下,但是此时要在web.xml中加入<context-param>,用它来指明你的applicationContext.xml的位置以供web容器来加载。按照Struts2 整合spring的官方给出的档案,写成:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext-*.xml,classpath*:applicationContext-*.xml</param-value>
</context-param>
附:从源码解析ContextLoaderListener、ContextLoader的主要作用
ContextLoaderListener源码
public class ContextLoaderListener extends ContextLoader implements
ServletContextListener {
private ContextLoader contextLoader; .....
//初始化上下文
public void contextInitialized(ServletContextEvent event) {
this.contextLoader = createContextLoader();
if (this.contextLoader == null) {
this.contextLoader = this;
}
//调用父类的initWebApplicationContext方法
this.contextLoader.initWebApplicationContext(event.getServletContext());
} }
ContextLoader源码
public class ContextLoader {
public static final String CONTEXT_CLASS_PARAM = "contextClass";
public static final String CONTEXT_ID_PARAM = "contextId";
public static final String CONTEXT_INITIALIZER_CLASSES_PARAM = "contextInitializerClasses";
public static final String CONFIG_LOCATION_PARAM = "contextConfigLocation";
public static final String LOCATOR_FACTORY_SELECTOR_PARAM = "locatorFactorySelector";
public static final String LOCATOR_FACTORY_KEY_PARAM = "parentContextKey";
private static final String DEFAULT_STRATEGIES_PATH = "ContextLoader.properties";
private static final Properties defaultStrategies;
private static final Map<ClassLoader, WebApplicationContext> currentContextPerThread;
private static volatile WebApplicationContext currentContext;
private WebApplicationContext context;
private BeanFactoryReference parentContextRef; //加载ContextLoader.properties
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());
} currentContextPerThread = new ConcurrentHashMap(1);
} ......
//初始化WebApplicationContext
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 {
//如果WebApplicationContext为空,则创建。
if (this.context == null) {
this.context = createWebApplicationContext(servletContext);
}
if (this.context instanceof ConfigurableWebApplicationContext) {
configureAndRefreshWebApplicationContext(
(ConfigurableWebApplicationContext) this.context,
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;
}
}
//创建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() + "]");
}
ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext) BeanUtils
.instantiateClass(contextClass);
return wac;
} ...... //配置、刷新WebApplicationContext
protected void configureAndRefreshWebApplicationContext(
ConfigurableWebApplicationContext wac, ServletContext sc) {
if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
String idParam = sc.getInitParameter("contextId");
if (idParam != null) {
wac.setId(idParam);
} else if ((sc.getMajorVersion() == 2)
&& (sc.getMinorVersion() < 5)) {
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX
+ ObjectUtils.getDisplayString(sc
.getServletContextName()));
} else {
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX
+ ObjectUtils.getDisplayString(sc.getContextPath()));
} } ApplicationContext parent = loadParentContext(sc); wac.setParent(parent);
wac.setServletContext(sc);
String initParameter = sc.getInitParameter("contextConfigLocation");
if (initParameter != null) {
wac.setConfigLocation(initParameter);
}
customizeContext(sc, wac);
wac.refresh();
}
//确认上下文class类型
protected Class<?> determineContextClass(ServletContext servletContext) {
String contextClassName = servletContext
.getInitParameter("contextClass");
if (contextClassName != null) {
try {
return ClassUtils.forName(contextClassName,
ClassUtils.getDefaultClassLoader());
} catch (ClassNotFoundException ex) {
throw new ApplicationContextException(
"Failed to load custom context class ["
+ contextClassName + "]", ex);
}
}
//contextClassName默认值:org.springframework.web.context.support.XmlWebApplicationContext
contextClassName = defaultStrategies
.getProperty(WebApplicationContext.class.getName());
try {
return ClassUtils.forName(contextClassName,
ContextLoader.class.getClassLoader());
} catch (ClassNotFoundException ex) {
throw new ApplicationContextException(
"Failed to load default context class [" + contextClassName
+ "]", ex);
}
} ......
}
ContextLoader.properties
# Default WebApplicationContext implementation class for ContextLoader.
# Used as fallback when no explicit context implementation has been specified as context-param.
# Not meant to be customized by application developers. org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext
从上面的源码可以得知:类ContextLoaderListener主要的作用是初始化上下文WebApplicationContext(接口)的实现类:org.springframework.web.context.support.XmlWebApplicationContext。
此外,在类ContextLoader中,方法configureAndRefreshWebApplicationContext用于部署contextConfigLocation。
ContextLoaderListener作用详解的更多相关文章
- ContextLoaderListener作用详解(转)
ContextLoaderListener监听器的作用就是启动Web容器时,自动装配ApplicationContext的配置信息.因为它实现了ServletContextListener这个接口,在 ...
- Linux(centos)系统各个目录的作用详解
Linux(centos)系统各个目录的作用详解 文件系统的类型 LINUX有四种基本文件系统类型:普通文件.目录文件.连接文件和特殊文件,可用file命令来识别. 普通文件:如文本文件.C语言元代码 ...
- shell脚本中常见的一些特殊符号和作用详解
这篇文章主要介绍了shell脚本中常见的一些特殊符号和它的作用详解,总结的很简洁,容易看懂,需要的朋友可以参考下 在编写Shell脚本时,我们需要会用到各种各样的特殊符号,通过这些特殊符号可以使我 ...
- linux(CENTOS)系统各个目录的作用详解
Linux(CentOS)系统各个目录的作用详解 文件的类型 LINUX有四种基本文件系统类型:普通文件.目录文件.连接文件和特殊文件,可用file命令来识别. 普通文件:如文本文件.C语言元代码.S ...
- MySQL中的主键,外键有什么作用详解
MySQL中的主键,外键有什么作用详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 学关系型数据库的同学,尤其在学习主键和外键时会产生一定的困惑.那么今天我们就把这个困惑连根拔起 ...
- Python中__init__.py文件的作用详解
转自http://www.jb51.net/article/92863.htm Python中__init__.py文件的作用详解 http://www.jb51.net/article/86580. ...
- jsp九大内置对象和其作用详解
jsp九大内置对象和其作用详解 JSP中一共预先定义了9个这样的对象,分别为:request.response.session.application.out.pagecontext.config.p ...
- [转载]java中import作用详解
[转载]java中import作用详解 来源: https://blog.csdn.net/qq_25665807/article/details/74747868 这篇博客讲的真的很清楚,这个作者很 ...
- C++中头文件与源文件的作用详解
一.C++ 编译模式 通常,在一个 C++ 程序中,只包含两类文件―― .cpp 文件和 .h 文件.其中,.cpp 文件被称作 C++ 源文件,里面放的都是 C++ 的源代码:而 .h 文件则被称作 ...
随机推荐
- MYSQL多实例配置与使用教程
原文http://www.111cn.net/database/mysql/58651.htm 在实际的开发过程中,可能会需要在一台服务器上部署多个MYSQL实例,那建议使用MYSQL官方的解决方案 ...
- UI1_UITableViewHomeWork
// // AppDelegate.m // UI1_UITableViewHomeWork // // Created by zhangxueming on 15/7/14. // Copyrigh ...
- OC4_遵守多个协议
// // Calulator.h // OC4_遵守多个协议 // // Created by zhangxueming on 15/6/24. // Copyright (c) 2015年 zha ...
- javascript之Array基础篇
整理了 Array 中很基础的要掌握的知识点,希望可以帮助初学者,也希望自己以后多用多融会贯通. 创建数组 使用Array构造函数: var a=new Array();//创建一个空数组 var a ...
- JVM内存分配
内存分配:当JVM运行起来的时候就会给内存划分空间,那么这块空间称之为运行时数据区.(备注:当一个Java源程序编译成class字节码文件之后,字节码文件里存放的都是二进制的汇编命令,当程序运行的时候 ...
- Sublime Text 2入门指南
Sublime Text 2入门指南 一天在iteye上看到范凯介绍一个开发工具(TextMate ),看下面的评论时看到Sublime Text 2.其实我一直喜欢editplus.百度了一番才 ...
- C89 和 C99的标准比较
本文转载自: C89和C99标准比较 原文转载自: http://blog.programfan.com/article.asp?id=14051 http://blog.csdn.net/xgb ...
- 《postfix MAIL服务搭建(第一篇):》RHEL6
初级篇:搭建发送端.接收端.邮件别名的添加从而达到邮件群发功能的实现. 我们都知道邮件服务器是2个服务端也就是说2个端口,一个是发送的端口,一个是收邮件的端口,我们平常所使用的发送,接收邮件的过程,只 ...
- 《搭建更新DNS集群服务》RHEL6
DNS服务器的更新: 一听就知道不止一台的DNS服务器,要是一台也用不着更新对吧?一般都是DNS集群. 一台DNS更新了,添加一条数据,下面的都要跟着它变. 主DNS服务器的配置 首先先配置DNS服务 ...
- 用jQuery解析复杂的xml结构文件
一个晚上的心血 <?xml version="1.0" encoding="UTF-8"?> <weibo><wbContent& ...