ContextLoaderListener容器初始化
2024-10-21 11:35:58
http://blog.csdn.net/qq924862077/article/details/52769754
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:applicationContext.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
在tomcat启动时,spring通过上述配置会初始化spring容器,注入applicationContext.xml中配置的bean以及其他一些配置
public class ContextLoaderListener extends ContextLoader implements ServletContextListener { public ContextLoaderListener() {
}
public ContextLoaderListener(WebApplicationContext context) {
super(context);
}
@Override
public void contextInitialized(ServletContextEvent event) {
initWebApplicationContext(event.getServletContext());
}
@Override
public void contextDestroyed(ServletContextEvent event) {
closeWebApplicationContext(event.getServletContext());
ContextCleanupListener.cleanupAttributes(event.getServletContext());
}
}
ContextLoderListener实现ServletContextListener接口,而该接口继承java的监听标记接口EventListener,表示当servlet容器启动时,就会接受通知,进而进行一系列的初始化操作。
public interface ServletContextListener extends EventListener { /**
* Receives notification that the web application initialization
* process is starting.
*
* <p>All ServletContextListeners are notified of context
* initialization before any filters or servlets in the web
* application are initialized.
*
* @param sce the ServletContextEvent containing the ServletContext
* that is being initialized
*/
public void contextInitialized(ServletContextEvent sce); /**
* Receives notification that the ServletContext is about to be
* shut down.
*
* <p>All servlets and filters will have been destroyed before any
* ServletContextListeners are notified of context
* destruction.
*
* @param sce the ServletContextEvent containing the ServletContext
* that is being destroyed
*/
public void contextDestroyed(ServletContextEvent sce);
}
- 判断是否已经存在WebApplicationContext(spring容器),如果存在,则抛出异常。
- 创建WebApplicationContext容器,从web.xml中获取context-param名称为contextClass的value,该类必须实现WebApplicationContext接口,如果没有指定,则默认使用xmlWebApplicationContext。
- 判断创建的WebApplicationContext容器是否为ConfigurableApplicationContext的实例或子类,如果是,则判断该容器是否至少刷新一次并且还没有关闭(是否有效),如果无效,则重新设置容器的id,并加载对应的contextConfigLocation配置(spring配置),
加载父容器,spring提供一个模板方法,如果需要配置父容器,可以继承ContextLoder,并覆盖loadParentContext方法。 - 线程绑定容器
/**
* Initialize Spring's web application context for the given servlet context,
* using the application context provided at construction time, or creating a new one
* according to the "{@link #CONTEXT_CLASS_PARAM contextClass}" and
* "{@link #CONFIG_LOCATION_PARAM contextConfigLocation}" context-params.
* @param servletContext current servlet context
* @return the new WebApplicationContext
* @see #ContextLoader(WebApplicationContext)
* @see #CONTEXT_CLASS_PARAM
* @see #CONFIG_LOCATION_PARAM
*/
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 {
// Store context in local instance variable, to guarantee that
// it is available on ServletContext shutdown.
if (this.context == null) {
//创建容器
this.context = createWebApplicationContext(servletContext);
}
if (this.context instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
if (!cwac.isActive()) {
// The context has not yet been refreshed -> provide services such as
// setting the parent context, setting the application context id, etc
if (cwac.getParent() == null) {
// The context instance was injected without an explicit parent ->
// determine parent for root web application context, if any.
ApplicationContext parent = loadParentContext(servletContext);
cwac.setParent(parent);
}
//如果容器无效,则重置contextId,且重新加载contextConfigLocation配置
configureAndRefreshWebApplicationContext(cwac, servletContext);
}
}
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
//线程绑定容器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;
}
}
最新文章
- Android 手机卫士--导航界面4的业务逻辑
- TCP那些事
- Codeforces Round #380(div 2)
- 界面绚丽的SharePoint仪表盘控件Nevron Gauge for SharePoint 控件详细介绍
- 获取发布版SHA1获取
- C++学习笔记之由文本文件读取数据到vector模板建立的二维数组 并存储为新的文本文件
- delphi 创建数据库配置文件(TIniFile)
- JQUERY省、市、县城市联动选择
- 基于ORACLE建表和循环回路来创建数据库存储过程SQL语句来实现
- leetcode 024
- 201521123078 《Java程序设计》第6周学习总结
- windows 系统下C++实现的多线程
- 搭建和测试 Redis 主备和集群
- Git版本控制:Gitlab及Coding.net的使用
- 暑假第二弹:基于docker的hadoop分布式集群系统的搭建和测试
- 【转】Apache与Tomcat有什么关系和区别
- 第18章:MongoDB-聚合操作--聚合管道--$sort
- REDIS 缓存的穿透,雪崩和热点key
- Arcgis Runtime for andriod 100 加载TPK
- 说说ASP.NET的IsPostBack
热门文章
- npm使用指南
- 25. Spring Boot使用自定义的properties【从零开始学Spring Boot】
- 【AngularJS】【03】使用AngularJS进行开发
- Shiro学习(7)与Web整合
- const的理解、const指针、指向const的指针
- Oracle 中for update和for update nowait的区别
- [ACM] hdu 1029 Ignatius and the Princess IV (动归或hash)
- Cocos2d-x 更改文字换行风格 ( cocos2dx change line )
- Hibernate学习三----------session详解
- php设计模式中的类型安全 指--只接受特定的对象 ---以避免发生错误