简介
虽然接触Spring框架时间挺久,但是里边的一些细节仍然了解的仍然不够深入,其中之一就是ContextLoaderListener,之前在网上差了一些资料始终没理解清楚,今天在一本书上偶遇,下来就简单总结看过书以后我对ContextLoaderListener的理解。
前提
首先明确一点,Spring并不是web应用的专属,只要是Java应用就可以借助Spring框架开发,甚至是桌面应用同样可以使用Spring框架。由于Spring的应用场景比较多,所以Spring中提供了多个类型的容器,如:Beanfactory,ApplicationContext,WebApplicationContext等,其中BeanFactory是SpringIOC容器的最基本设施,其他两个都是基于BeanFactory扩展而来,所以说BeanFactory相对比较底层,功能也相对较少,我们在普通Java应用中一般使用ApplicationContext,但是WebApplicationContext是为Web应用量身定做的。
详述
下边的xml代码是web应用中使用Spring框架时Web.xml配置文件中的一部分,第一次看师傅的这个配置时有点懵,查资料也是一头雾水。
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
ContextLoaderListener继承ContextLoader,在ContextLoader中的initWebApplicationContext方法会调用contextConfigLocation这个初始化数据,并且initWebApplicationContext方法又会被ContextLoaderListener调用,也就是说contextConfigLocation这个初始化数据就是个这个监听器定义的,同时要注意,WebApplicationContextLoader这个Spring容器也是在这个监听器中启动的。
web应用的使用必须有一个web容器,如Tomcat,Jetty等,ContextLoaderListener会监听web容器的启动,当web容器启动的时候这个监听器会自动执行,ContextLoaderListener源码如下:
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
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());
}
}
先不要管Spring框架是怎么调用这个类实例当中的方法的,根据这个类中的代码已经大概能够知道ContextLoaderListener是干嘛的,显然contextInitialized方法是web容器启动时被调用的方法,web容器启动肯定会加载已经发布的web应用,每一个应用都会有自己的ServletContext,这个方法contextInitialized传入了一个事件ServletContextEvent,不用管事件是干嘛的,总之他可以获取ServletContext实例,并且传给了WebApplicationContext,而我们知道,WebApplicationContext是Spring针对web应用的一个IOC容器,这个IOC容器在启动的时候会自动实例化Singleton作用域的bean,而web中的bean理论上需要拥有ServletContext,或者说WebApplicationContext实例本身就必须拥有实例化后的ServletContext,如果没有给WebApplicationContext提供实例化的ServletContext,这个IOC容器启动时应该会报错。
ContextLoaderListener类当中的另一个方法contextDestroyed显然是在应用关闭时被调用执行一些清理工作,而且里边还牵扯到了ContextCleanupListener监听器,此处不详述。
总之,ContextLoaderListener监听器就是在监听web容器的状态,如启动和关闭,并且在状态发生变化时会被调用相应的方法,在这里就是在启动时个WebApplicationContext传入ServletContext实例,关闭时执行一些清理工作。