上一篇講解了Spring通過ContextLoader類的initWebApplicationContext
方法創建的WebApplicationContext
實爲XmlWebApplicationContext
實例
再看initWebApplicationContext
方法的源碼:
/**
* 爲了講重點,省略了部分源碼
*/
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
...
try {
// Store context in local instance variable, to guarantee that
// it is available on ServletContext shutdown.
if (this.context == null) {
this.context = createWebApplicationContext(servletContext); //312行
}
if (this.context instanceof ConfigurableWebApplicationContext) { //314行
//重點就是這裏的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
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);
}
}
...
return this.context;
}
...
}
從initWebApplicationContext
方法可以看出來,有判斷XmlWebApplicationContext
是否屬於ConfigurableWebApplicationContext
類型
來看一下ConfigurableApplicationContext的源碼
* Copyright 2002-2014 the original author or authors.
package org.springframework.web.context;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import org.springframework.context.ConfigurableApplicationContext;
/**
* Interface to be implemented by configurable web application contexts.
* Supported by {@link ContextLoader} and
* {@link org.springframework.web.servlet.FrameworkServlet}.
*
* <p>Note: The setters of this interface need to be called before an
* invocation of the {@link #refresh} method inherited from
* {@link org.springframework.context.ConfigurableApplicationContext}.
* They do not cause an initialization of the context on their own.
*
* @author Juergen Hoeller
* @since 05.12.2003
* @see #refresh
* @see ContextLoader#createWebApplicationContext
* @see org.springframework.web.servlet.FrameworkServlet#createWebApplicationContext
*/
public interface ConfigurableWebApplicationContext extends WebApplicationContext, ConfigurableApplicationContext {
/**
* Prefix for ApplicationContext ids that refer to context path and/or servlet name.
*/
String APPLICATION_CONTEXT_ID_PREFIX = WebApplicationContext.class.getName() + ":";
/**
* Name of the ServletConfig environment bean in the factory.
* @see javax.servlet.ServletConfig
*/
String SERVLET_CONFIG_BEAN_NAME = "servletConfig";
/**
* Set the ServletContext for this web application context.
* <p>Does not cause an initialization of the context: refresh needs to be
* called after the setting of all configuration properties.
* @see #refresh()
*/
void setServletContext(ServletContext servletContext);
/**
* Set the ServletConfig for this web application context.
* Only called for a WebApplicationContext that belongs to a specific Servlet.
* @see #refresh()
*/
void setServletConfig(ServletConfig servletConfig);
/**
* Return the ServletConfig for this web application context, if any.
*/
ServletConfig getServletConfig();
/**
* Set the namespace for this web application context,
* to be used for building a default context config location.
* The root web application context does not have a namespace.
*/
void setNamespace(String namespace);
/**
* Return the namespace for this web application context, if any.
*/
String getNamespace();
/**
* Set the config locations for this web application context in init-param style,
* i.e. with distinct locations separated by commas, semicolons or whitespace.
* <p>If not set, the implementation is supposed to use a default for the
* given namespace or the root web application context, as appropriate.
*/
void setConfigLocation(String configLocation);
/**
* Set the config locations for this web application context.
* <p>If not set, the implementation is supposed to use a default for the
* given namespace or the root web application context, as appropriate.
*/
void setConfigLocations(String... configLocations);
/**
* Return the config locations for this web application context,
* or {@code null} if none specified.
*/
String[] getConfigLocations();
}
可以看出來
- ConfigurableWebApplicationContext是個接口,而且顧名思義:可配置的WebApplicationContext
- ConfigurableWebApplicationContext類定義了8個方法,主要是關於context和config的get和set
其實就是在上面講到的ContextLoader類的initWebApplicationContext
方法,接着調用了configureAndRefreshWebApplicationContext
方法,查看其源碼:
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
// The application context id is still set to its original default value
// -> assign a more useful id based on available information
String idParam = sc.getInitParameter(CONTEXT_ID_PARAM);
if (idParam != null) {
wac.setId(idParam);
}
else {
// Generate default id...
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
ObjectUtils.getDisplayString(sc.getContextPath()));
}
}
wac.setServletContext(sc);
String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
if (configLocationParam != null) {
wac.setConfigLocation(configLocationParam);
}
// The wac environment's #initPropertySources will be called in any case when the context
// is refreshed; do it eagerly here to ensure servlet property sources are in place for
// use in any post-processing or initialization that occurs below prior to #refresh
ConfigurableEnvironment env = wac.getEnvironment();
if (env instanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment) env).initPropertySources(sc, null);
}
customizeContext(sc, wac);
wac.refresh();
}
其中String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);代碼就是獲取我們經常在web.xml裏配置的contextConfigLocation
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/spring/*.xml</param-value>
</context-param>
若web.xml配置的是上面的代碼,那configLocationParam的值就是classpath*:/spring/*.xml,該值接着就被set到AbstractRefreshableConfigApplicationContext類的configLocations變量裏,講到這裏就不得不貼一下類關係圖了