容器启动的时候读取web.xml文件
有spring 启动配置
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
找到ContextLoaderListener类
ContextLoaderListener继承ContextLoader 实现ServletContextListener接口
ContextLoader 方法里有加载xml文件的方法,ServletContextListener接口是servlet-api.jar里的接口
public abstract interface ServletContextListener
extends EventListener
{
public abstract void contextInitialized(ServletContextEvent paramServletContextEvent);
public abstract void contextDestroyed(ServletContextEvent paramServletContextEvent);
}
EventListener类是空的,应该是个监听事件
ServletContextListener接口大致应该是监听容器启动事件
好,返回主要问题上
在 ContextLoaderListener类里有下面这个方法
/**
* Initialize the root web application context.
* 初始化一个context
* 怎么调用如果有大神知道请告诉一下
*/
@Override
public void contextInitialized(ServletContextEvent event) {
//方法在ContextLoader类里
initWebApplicationContext(event.getServletContext());
}
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
//这里判断一下web应用是否已经有spring容器启动
//如果有被加载过,将抛出异常。提示是否放置了多个ContextLoaderListener。
if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {
throw new IllegalStateException(
"Cannot initialize context because there is already a root application context present - " +
"check whether you have multiple ContextLoader* definitions in your web.xml!");
}
Log logger = LogFactory.getLog(ContextLoader.class);
servletContext.log("Initializing Spring root WebApplicationContext");
if (logger.isInfoEnabled()) {
logger.info("Root WebApplicationContext: initialization started");
}
long startTime = System.currentTimeMillis();
try {
// Store context in local instance variable, to guarantee that
// it is available on ServletContext shutdown.
//下面这句是创建WebApplicationContext的主过程。
if (this.context == null) {
this.context = createWebApplicationContext(servletContext);
}
//如果当前的应用上下文对象是 ConfigurableWebApplicationContext
if (this.context instanceof ConfigurableWebApplicationContext) {
//强制类型转换
ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
// 如果应用上下文没有生效
if (!cwac.isActive()) {
// The context has not yet been refreshed -> provide services such as
// setting the parent context, setting the application context id, etc
// 如果该上下文对象为null
if (cwac.getParent() == null) {
// The context instance was injected without an explicit parent ->
// determine parent for root web application context, if any.
//加载父上下文
ApplicationContext parent = loadParentContext(servletContext);
// 设置父上下文
cwac.setParent(parent);
}
configureAndRefreshWebApplicationContext(cwac, servletContext);
}
}
//创建完的context置于servletContext中,
//这样Spring容器的宿主就是ServletContext
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
////获取当前线程的类加载器
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
// 如果ContextLoader的类加载器和当前线程的类加载器一样,则应用上下文对象赋值给currentContext
if (ccl == ContextLoader.class.getClassLoader()) {
currentContext = this.context;
}
else if (ccl != null) {
currentContextPerThread.put(ccl, this.context);
}
if (logger.isDebugEnabled()) {
logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" +
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");
}
if (logger.isInfoEnabled()) {
long elapsedTime = System.currentTimeMillis() - startTime;
logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");
}
// 返回应用上下文对象
return this.context;
}
catch (RuntimeException ex) {
logger.error("Context initialization failed", ex);
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
throw ex;
}
catch (Error err) {
logger.error("Context initialization failed", err);
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err);
throw err;
}
}