一.概述
ContextLoaderListener监听器的作用就是启动Web容器时,自动装配ApplicationContext的配置信息。因为它实现了ServletContextListener这个接口,在web.xml配置这个监听器,启动容器时,就会默认执行它实现的方法。
二.初始化
1.配置
在web.xml中配置如下,则web容器启动时会触发监听器ContextLoaderListener
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
2.ContextLoaderListener实例化
ContextLoaderListener类实现了
ServletContextListener接口,继承了ContextLoder类,并且持有一个ContextLoder实例对象,ContextLoader主要处理XmlWebApplicationContext的创建。
当web容器启动时触发监听器,ContextLoaderListener调用无参构造函数实例化。
3.启动
接口ServletContextListener的contextInitialized(ServletContextEvent paramServletContextEvent)方法初始化上下文,ContextLoaderListener实现了contextInitialized方法。
所以监听器被触发后,会调用此方法
/**
* Initialize the root web application context.
*/
public void contextInitialized(ServletContextEvent event) {
// createContextLoader()返回null
this.contextLoader = createContextLoader();
if (this.contextLoader == null) {
// 为持有的ContextLoader实例赋值
this.contextLoader = this;
}
// ContextLoader实例对象实例化上下文
this.contextLoader.initWebApplicationContext(event.getServletContext());
}
@Deprecated 废弃
protected ContextLoader createContextLoader() {
return null;
}
4.下一篇
详情请看下一篇: Spring初始化 - ContextLoader
三.无注释源码
package org.springframework.web.context;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
private ContextLoader contextLoader;
public ContextLoaderListener() {
}
public ContextLoaderListener(WebApplicationContext context) {
super(context);
}
public void contextInitialized(ServletContextEvent event) {
this.contextLoader = createContextLoader();
if (this.contextLoader == null) {
this.contextLoader = this;
}
this.contextLoader.initWebApplicationContext(event.getServletContext());
}
// 废弃
@Deprecated
protected ContextLoader createContextLoader() {
return null;
}
// 废弃
@Deprecated
public ContextLoader getContextLoader() {
return this.contextLoader;
}
public void contextDestroyed(ServletContextEvent event) {
if (this.contextLoader != null) {
this.contextLoader.closeWebApplicationContext(event.getServletContext());
}
ContextCleanupListener.cleanupAttributes(event.getServletContext());
}
}
四.注释源码
package org.springframework.web.context;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
/**
* 监听Spring的根(WebApplicationContext)的启动和销毁
*
* 1.如果在web.xml中存在org.springframework.web.util.Log4jConfigListener的监听器
* 本监听器需要在其后注册才能起效
*
* 2.从Spring 3.1起,ContextLoaderListener支持通过{@link #ContextLoaderListener(WebApplicationContext)}构造函数
* 注入根Web应用程序上下文,允许在Servlet 3.0+环境中进行编程配置。
* 看{@link org.springframework.web.WebApplicationInitializer}使用示例。
*/
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
// 实现Spring的初始化
private ContextLoader contextLoader;
/**
* 1. 创建一个新的ContextLoaderListener,他将基于servlet参数"contextClass"和"contextConfigLocation"
* 创建一个web应用程序上下文
* 有关每个的默认值的详细信息,请参阅{@link ContextLoader}类文档
*
* 2. 在web.xml中声明ContextLoaderListener为监听器时,需要无参构造函数,这个构造函数通常就会被用到
*
* 3. 创建的应用程序上下文将被注册到ServletContext下
* 属性名WebApplicationContext.java#ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
*
* 4.当此监听器调用{@link #contextDestroyed}方法时,Spring应用程序上下文将关闭
*/
public ContextLoaderListener() {
}
/**
* 1. 使用给定的应用程序上下文context创建一个新的ContextLoaderListener。
* 这个构造函数在Servlet 3.0+环境中很有用,通过{@link javax.servlet.ServletContext#addListener}可以注册监听器
*
* 2.这个上下文context可能已经或者还没有刷新:org.springframework.context.ConfigurableApplicationContext#refresh()
* 如果上下文context是ConfigurableWebApplicationContext的实现,并且还没有刷新(推荐的方式)
* 会有以下情况:
* (1)如果给定上下文context还没有分配id:org.springframework.context.ConfigurableApplicationContext#setId
* 会给他分配一个id
* (2)ServletContext和ServletConfig对象将被委派给上下文对象context
* (3)org.springframework.web.context.ContextLoader#customizeContext将被调用
* (4)任何org.springframework.context.ApplicationContextInitializer将通过初试参数"contextInitializerClasses"指定
* (5)org.springframework.context.ConfigurableApplicationContext#refresh将被调用
*
* 3.如果上下文content已经刷新或不是ConfigurableWebApplicationContext的实现,
* 上述任何一种都不会在用户根据自己的具体需求执行这些操作(或不执行)的假设下进行
*
* 4.有关使用示例,请参阅{@link org.springframework.web.WebApplicationInitializer}
*
* 5.无论如何,给定的应用程序上下文content将被注册到ServletContext中,
* 属性名为WebApplicationContext#ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE},
* 并且在此监听器调用{@link #contextDestroyed}方法时,Spring应用程序上下文将关闭。
*/
public ContextLoaderListener(WebApplicationContext context) {
super(context);
}
/**
* 初始化web应用程序上下文的根
*/
public void contextInitialized(ServletContextEvent event) {
this.contextLoader = createContextLoader();
if (this.contextLoader == null) {
this.contextLoader = this;
}
// ContextLoader实现初始化
this.contextLoader.initWebApplicationContext(event.getServletContext());
}
// 弃用
@Deprecated
protected ContextLoader createContextLoader() {
return null;
}
// 弃用
@Deprecated
public ContextLoader getContextLoader() {
return this.contextLoader;
}
/**
* 关闭应用程序的上下文
*/
public void contextDestroyed(ServletContextEvent event) {
if (this.contextLoader != null) {
this.contextLoader.closeWebApplicationContext(event.getServletContext());
}
ContextCleanupListener.cleanupAttributes(event.getServletContext());
}
}