共同学习Spring源码--ContextLoaderListener和ContextCleanupListener

本文探讨了Spring框架中的ContextLoaderListener和ContextCleanupListener。这两个类都实现了ServletContextListener接口,用于web应用程序的初始化和关闭。contextInitialized方法在web应用启动时初始化上下文,而contextDestroyed方法在关闭前销毁上下文。ContextCleanupListener的cleanupAttributes方法负责清理以'org.springframework.'开头的属性,若属性实现DisposableBean接口,则调用其destroy方法进行销毁。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这个类继承了ContextLoader,实现了ServletContextListener接口。

ServletContextListener接口继承了util包的EventListener接口,EventListener没有任何方法。

这个接口定义了两个方法:

public void contextInitialized(ServletContextEvent sce);

这个方法的注释是在说该方法是通知web应用程序的初始化工作开始了,在所有filter和servlet初始化之前,这个监听器接口的实现类被告知进行上下文的初始化工作。

public void contextDestroyed(ServletContextEvent sce);

这个方法的注释是在说该方法是通知servlet上下文即将关闭。任何filter和servlet都会在这个监听器接口实现类进行上下文销毁之前销毁。

现在来看ContextLoaderListener对这两个方法的实现:

@Override
public void contextInitialized(ServletContextEvent event) {
initWebApplicationContext(event.getServletContext());
}

这个initWebApplicationContext方法是该监听器实现类的父类ContextLoader类的方法,之后会进入这个类学习源代码。

public void contextDestroyed(ServletContextEvent event) {
closeWebApplicationContext(event.getServletContext());
ContextCleanupListener.cleanupAttributes(event.getServletContext());
}

这个closeWebApplicationContext方法也是ContextLoader类的方法。


下面进入ContextCleanupListener,这个监听器实现类也实现了ServletContextListener,只实现了这个接口。

且抽象方法有意义的实现只有一个

@Override
public void contextDestroyed(ServletContextEvent event) {
cleanupAttributes(event.getServletContext());
}

static void cleanupAttributes(ServletContext sc) {
Enumeration<String> attrNames = sc.getAttributeNames();
while (attrNames.hasMoreElements()) {
String attrName = attrNames.nextElement();
if (attrName.startsWith("org.springframework.")) {
Object attrValue = sc.getAttribute(attrName);
if (attrValue instanceof DisposableBean) {
try {
((DisposableBean) attrValue).destroy();
}
catch (Throwable ex) {
logger.error("Couldn't invoke destroy method of attribute with name '" + attrName + "'", ex);
}
}
}
}
}

contextDestroyed实现里调用了cleanupAttributes方法,这个静态方法在ContextLoaderListener中得到了静态的调用,在ContextCleanupListener的成员方法ContextDestroyed中也被调用,前一个调用还算正常,后一个调用是在成员方法中调用静态方法,觉得有点奇怪。。。但没什么不妥的。。。

来看这个静态方法,先是获取参数ServletContext的所有参数名,返回一个Enumeration接口,这是一个古老的类,现在基本被List实现类替代。得到后遍历这个Enumeration,将所有以“org.springframework”开头的参数名和该参数名对应的值获取,如果参数值属于DisposableBean接口的实现类,则调用该参数值的destroy方法销毁,过程中会抛出异常,然后由logger来输出调试信息。

DisposableBean是一个接口,只有一个destroy方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值