参考网址: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作用详解的更多相关文章

  1. ContextLoaderListener作用详解(转)

    ContextLoaderListener监听器的作用就是启动Web容器时,自动装配ApplicationContext的配置信息.因为它实现了ServletContextListener这个接口,在 ...

  2. Linux(centos)系统各个目录的作用详解

    Linux(centos)系统各个目录的作用详解 文件系统的类型 LINUX有四种基本文件系统类型:普通文件.目录文件.连接文件和特殊文件,可用file命令来识别. 普通文件:如文本文件.C语言元代码 ...

  3. shell脚本中常见的一些特殊符号和作用详解

    这篇文章主要介绍了shell脚本中常见的一些特殊符号和它的作用详解,总结的很简洁,容易看懂,需要的朋友可以参考下   在编写Shell脚本时,我们需要会用到各种各样的特殊符号,通过这些特殊符号可以使我 ...

  4. linux(CENTOS)系统各个目录的作用详解

    Linux(CentOS)系统各个目录的作用详解 文件的类型 LINUX有四种基本文件系统类型:普通文件.目录文件.连接文件和特殊文件,可用file命令来识别. 普通文件:如文本文件.C语言元代码.S ...

  5. MySQL中的主键,外键有什么作用详解

    MySQL中的主键,外键有什么作用详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 学关系型数据库的同学,尤其在学习主键和外键时会产生一定的困惑.那么今天我们就把这个困惑连根拔起 ...

  6. Python中__init__.py文件的作用详解

    转自http://www.jb51.net/article/92863.htm Python中__init__.py文件的作用详解 http://www.jb51.net/article/86580. ...

  7. jsp九大内置对象和其作用详解

    jsp九大内置对象和其作用详解 JSP中一共预先定义了9个这样的对象,分别为:request.response.session.application.out.pagecontext.config.p ...

  8. [转载]java中import作用详解

    [转载]java中import作用详解 来源: https://blog.csdn.net/qq_25665807/article/details/74747868 这篇博客讲的真的很清楚,这个作者很 ...

  9. C++中头文件与源文件的作用详解

    一.C++ 编译模式 通常,在一个 C++ 程序中,只包含两类文件―― .cpp 文件和 .h 文件.其中,.cpp 文件被称作 C++ 源文件,里面放的都是 C++ 的源代码:而 .h 文件则被称作 ...

随机推荐

  1. 北大ACM(POJ1003-Hangover)

    Question:http://poj.org/problem?id=1003问题点:水题. Memory: 220K Time: 0MS Language: C++ Result: Accepted ...

  2. Linux下DNS服务器的基本搭建

    技术交流群:286866978 安装与配置 1. 装载光驱 2. 卸载光驱 3. 将安装包放在合适的文件夹并解压(有的更换光盘需要重新装载) 4. 安装 5. 重定向配置文件 6. 配置named.c ...

  3. 【原创】ORA-04068: 已丢弃程序包 的当前状态研究

    不久前在市检的生产环境上有个存储过程执行报错,错误信息如下: ORA: 已丢弃程序包 的当前状态 ORA: package "ZHANGXSH.PR_TEST" 的当前状态失效 O ...

  4. ionic中的生命周期函数

    //ionic中的生命周期函数 onPageLoaded(){ //page初始化时 console.log("page 1 : page loaded"); } //在这里可以做 ...

  5. 《HTML5与CSS3基础教程》学习笔记 ——Four Day

    第十六章 1.    输入和元素 电子邮件框 <input type="email"> 搜索框 <input type="search"> ...

  6. 【leetcode】15. 3Sum

    题目描述: Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find ...

  7. Aborting a running program

    In the event that a calculation appears to be running excessively long, one can abort thecalculation ...

  8. javascript给不能修改的函数增加额外处理的方法

    不知道是否可行,但姑且google之. 查看到相关的stack overflow(堆栈溢出)帖子:http://stackoverflow.com/questions/1659219/add-to-a ...

  9. oc常见误区

    1.同步请求可以从因特网请求数据,一旦发送同步请求,程序将停止用户交互,直至服务器返回数据完成,才可以进行下一步操作, 2.异步请求不会阻塞主线程,而会建立一个新的线程来操作,用户发出异步请求后,依然 ...

  10. [sql server] 如何阻止SELECT * 语句

    我们每个人都知道是个不好的做法,但有时我们还是要这样做:我们执行SELECT * 语句.这个方法有很多弊端: 你从你的表里返回每个列,甚至后期加的列.想下如果你的查询里将来加上了VARCHAR(MAX ...