今天看Spring web源代码解析时发现,原来上下文是在加载web.xml的时候就会创建根上下文,究竟是怎样创建的呢,一开始我也不明白,但是看了web的启动流程后就明白了,那么下面我们先看看web服务器的启动流程
1.启动一个WEB项目的时候,容器(如:Tomcat)会去读它的配置文件web.xml.读两个节点: <listener></listener> 和 <context-param></context-param>
2.紧接着,容器创建一个ServletContext(上下文),这个WEB项目所有部分都将共享这个上下文.
3.容器将<context-param></context-param>转化为键值对,并交给ServletContext.
4.容器创建<listener></listener>中的类实例,即创建监听.
5.在监听中会有contextInitialized(ServletContextEvent args)初始化方法,在这个方法中获得
ServletContext = ServletContextEvent.getServletContext();
context-param的值 = ServletContext.getInitParameter("context-param的键");
6.得到这个context-param的值之后,你就可以做一些操作了.注意,这个时候你的WEB项目还没有完全启动完成.这个动作会比所有的Servlet都要早.
换句话说,这个时候,你对<context-param>中的键值做的操作,将在你的WEB项目完全启动之前被执行.
7.举例.你可能想在项目启动之前就打开数据库.
那么这里就可以在<context-param>中设置数据库的连接方式,在监听类中初始化数据库的连接.
8.这个监听是自己写的一个类,除了初始化方法,它还有销毁方法.用于关闭应用前释放资源.比如说数据库连接的关闭.
好,在web项目中使用过Spring框架的都知道,必须在web.xml中配置一个一:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
代码:
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
private ContextLoader contextLoader;
public ContextLoaderListener() {
}
public ContextLoaderListener(WebApplicationContext context) {
super(context);
}
/**
* Initialize the root web application context.
*/
public void contextInitialized(ServletContextEvent event) {
this.contextLoader = createContextLoader();
if (this.contextLoader == null) {
this.contextLoader = this;
}
this.contextLoader.initWebApplicationContext(event.getServletContext());
}
/**
* Create the ContextLoader to use. Can be overridden in subclasses.
* @return the new ContextLoader
* @deprecated in favor of simply subclassing ContextLoaderListener itself
* (which extends ContextLoader, as of Spring 3.0)
*/
@Deprecated
protected ContextLoader createContextLoader() {
return null;
}
/**
* Return the ContextLoader used by this listener.
* @return the current ContextLoader
* @deprecated in favor of simply subclassing ContextLoaderListener itself
* (which extends ContextLoader, as of Spring 3.0)
*/
@Deprecated
public ContextLoader getContextLoader() {
return this.contextLoader;
}
/**
* Close the root web application context.
*/
public void contextDestroyed(ServletContextEvent event) {
if (this.contextLoader != null) {
this.contextLoader.closeWebApplicationContext(event.getServletContext());
}
ContextCleanupListener.cleanupAttributes(event.getServletContext());
}
}
大家可以看到,这个类里面也有一个contextInitialized(ServletContextEvent args)初始化方法,方法里通过调用父类的方法:contextLoader.initWebApplicationContext(event.getServletContext());来创建Spring IOC容器的根上下文,具体怎么创建这里就不详述,有兴趣的可以去看一下Spring的源码解析。
其实我们如果自己写一些监听类,然后在web.xml里配置一下那么就可以在项目加载完成之前做好更多的初始化工作,但是如果设置得太多的,想必会影响项目加载速度,所以还是适当添加的好,如果有什么说得不对的地方,请多多指教