一.写在前面
1.ServletContext 这里说的它是J2EE规范里面的 ServletContext 即:Servlet上下文。
2.WebApplicationContext 指的是Spring MVC Web应用上下文,有人也叫它Spring Web容器上下文。
二.二者之间的关系
其实WebApplicationContext是ServletContext里面的一个属性(attribute),为什么这么说?
因为当web容器启动一个Spring MVC的web项目的时候,其实最终都是启动了一个ServletContext,里面的各个Servlet中可以共享这个上下文,我们可以理解为网站内共有的属性,SpringMVC的功能无非是给我们提供了一个框架的东东,这个东东是干什么的呢?我个人理解就是这个帮助你很容易实现无数个Servlet功能的框架(简单实用一些注解和配置文件就可以搞定一个复杂的Servlet实现)。它怎么帮助我们的?其实它的帮我们创建的底层的Servlet其实也是需要有一个落地的点,其实就是WebApplicationContext。
三.上源码
web.xml
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
ContextLoaderListener
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
private ContextLoader contextLoader;
public ContextLoaderListener() {
}
public ContextLoaderListener(WebApplicationContext context) {
super(context);
}
public void contextInitialized(ServletContextEvent event) {
this.contextLoader = this.createContextLoader();
if(this.contextLoader == null) {
this.contextLoader = this;
}
this.contextLoader.initWebApplicationContext(event.getServletContext());
}
...
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
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!");
} else {
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 {
if(this.context == null) {
this.context = this.createWebApplicationContext(servletContext);
}
if(this.context instanceof ConfigurableWebApplicationContext) {
ConfigurableWebApplicationContext err = (ConfigurableWebApplicationContext)this.context;
if(!err.isActive()) {
if(err.getParent() == null) {
ApplicationContext elapsedTime = this.loadParentContext(servletContext);
err.setParent(elapsedTime);
}
this.configureAndRefreshWebApplicationContext(err, servletContext);
}
}
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
ClassLoader err1 = Thread.currentThread().getContextClassLoader();
if(err1 == ContextLoader.class.getClassLoader()) {
currentContext = this.context;
} else if(err1 != null) {
currentContextPerThread.put(err1, 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 elapsedTime1 = System.currentTimeMillis() - startTime;
logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime1 + " ms");
}
return this.context;
} catch (RuntimeException var8) {
logger.error("Context initialization failed", var8);
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, var8);
throw var8;
} catch (Error var9) {
logger.error("Context initialization failed", var9);
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, var9);
throw var9;
}
}
}