spring 源码、jar下载地址:http://repo.springsource.org/libs-release-local/
1、spring监听器org.springframework.web.context.ContextLoaderListener,监听器实现了接口javax.servlet.ServletContextListener接口,
在web.xml配置了ContextLoaderListener这个监听器,启动容器时,就会默认执行它实现的方法contextInitialized和contextDestroyed。
ServletContext:是一个全局的储存信息的空间,服务器开始,其就存在,服务器关闭,其才释放。request,一个用户可有多个;session,一个用户一个;而servletContext,所有用户共用一个。所以,为了节省空间,提高效率,ServletContext中,要放必须的、重要的、所有用户需要共享的线程又是安全的一些信息。表示了一个Web应用程序的上下文是Servlet与Servlet容器之间直接通信的接口,Servlet容器在启动一个web应用时,会为它创建一个ServletContext对象,每个web应用有唯一的ServletContext对象,同一个web应用的所有Servlet对象共享一个 ServletContext,Servlet对象可以通过它来访问容器中的各种资源。
ApplicationContext:的中文意思是“应用前后关系”,它继承自BeanFactory接口,除了包含BeanFactory的所有功能之外,在国际化支持、资源访问(如URL和文件)、事件传播等方面进行了良好的支持,被推荐为Java EE应用之首选,可应用在Java APP与Java Web中。
2、ContextLoaderListener中关联了ContextLoader 这个类,所以整个加载配置过程由ContextLoader 来完成.
执行初始化中关ContextLoader
public classContextLoader
{
publicstatic final String CONFIG_LOCATION_PARAM = "contextConfigLocation";
//ContextLoader根据web.xml中配置的contextConfigLocation参数名param-name,加载param-value
private static final StringDEFAULT_STRATEGIES_PATH = "ContextLoader.properties";
// 文件中配置org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext
//加载ContextLoader.properties文件中的数据
static {
try {
ClassPathResourceresource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, ContextLoader.class);
defaultStrategies =PropertiesLoaderUtils.loadProperties(resource);
}
catch (IOException ex) {
throw newIllegalStateException("Could not load 'ContextLoader.properties': " +ex.getMessage());
}
}
//调用ContextLoader中的initWebApplicationContext方法
public WebApplicationContextinitWebApplicationContext(ServletContext servletContext)
throwsIllegalStateException, BeansException {
if(servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE)!= null) {
throw newIllegalStateException(
"Cannotinitialize context because there is already a root application context present- " +
"checkwhether you have multiple ContextLoader* definitions in your web.xml!");
}
servletContext.log("InitializingSpring root WebApplicationContext");
if (logger.isInfoEnabled()) {
logger.info("RootWebApplicationContext: initialization started");
}
long startTime =System.currentTimeMillis();
try {
// Determine parentfor root web application context, if any.
ApplicationContextparent = loadParentContext(servletContext);
// Store context inlocal instance variable, to guarantee that
// it is availableon ServletContext shutdown.
this.context =createWebApplicationContext(servletContext, parent);
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,this.context);
currentContextPerThread.put(Thread.currentThread().getContextClassLoader(),this.context);
if (logger.isDebugEnabled()){
logger.debug("Publishedroot WebApplicationContext as ServletContext attribute with name [" +
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE+ "]");
}
if(logger.isInfoEnabled()) {
longelapsedTime = System.currentTimeMillis() - startTime;
logger.info("RootWebApplicationContext: initialization completed in " + elapsedTime +" ms");
}
return this.context;
}
catch (RuntimeException ex) {
logger.error("Contextinitialization failed", ex);
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,ex);
throw ex;
}
catch (Error err) {
logger.error("Contextinitialization failed", err);
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,err);
throw err;
}
}
从上面的代码大家应该明白了Spring初始化之后,将ApplicationContext存到在了两个地方
1.request.getSession().getServletContext().getAttribute("org.springframework.web.context.WebApplicationContext.ROOT")
2、WebApplicationContext content=CondextLoader.getCurrentWebApplicationContext()