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

这个类继承了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方法。

你可能感兴趣的:(共同学习Spring源码--ContextLoaderListener和ContextCleanupListener)