org.springframework.web.context
public class: ContextLoader [javadoc |
source]
java.lang.Object
org.springframework.web.context.ContextLoader
Performs the actual initialization work for the root application context.
Called by
ContextLoaderListener and
ContextLoaderServlet .
Looks for a "contextClass" parameter
at the web.xml context-param level to specify the context
class type, falling back to the default of
org.springframework.web.context.support.XmlWebApplicationContext
if not found. With the default ContextLoader implementation, any context class
specified needs to implement the ConfigurableWebApplicationContext interface.
Processes a "contextConfigLocation"
context-param and passes its value to the context instance, parsing it into
potentially multiple file paths which can be separated by any number of
commas and spaces, e.g. "WEB-INF/applicationContext1.xml,
WEB-INF/applicationContext2.xml". Ant-style path patterns are supported as well,
e.g. "WEB-INF/*Context.xml,WEB-INF/spring*.xml" or "WEB-INF/**/*Context.xml".
If not explicitly specified, the context implementation is supposed to use a
default location (with XmlWebApplicationContext: "/WEB-INF/applicationContext.xml").
Note: In case of multiple config locations, later bean definitions will
override ones defined in previously loaded files, at least when using one of
Spring's default ApplicationContext implementations. This can be leveraged
to deliberately override certain bean definitions via an extra XML file.
Above and beyond loading the root application context, this class
can optionally load or obtain and hook up a shared parent context to
the root application context. See the
#loadParentContext(ServletContext) method for more information.
| Field Summary |
|---|
| public static final String | CONTEXT_CLASS_PARAM | Config param for the root WebApplicationContext implementation class to
use: "contextClass" |
| public static final String | CONFIG_LOCATION_PARAM | Name of servlet context parameter (i.e., "contextConfigLocation")
that can specify the config location for the root context, falling back
to the implementation's default otherwise.Also see:
- org.springframework.web.context.support.XmlWebApplicationContext#DEFAULT_CONFIG_LOCATION
|
| public static final String | LOCATOR_FACTORY_SELECTOR_PARAM | Optional servlet context parameter (i.e., "locatorFactorySelector")
used only when obtaining a parent context using the default implementation
of #loadParentContext(ServletContext servletContext) .
Specifies the 'selector' used in the
ContextSingletonBeanFactoryLocator#getInstance(String selector)
method call, which is used to obtain the BeanFactoryLocator instance from
which the parent context is obtained.
The default is classpath*:beanRefContext.xml,
matching the default applied for the
ContextSingletonBeanFactoryLocator#getInstance() method.
Supplying the "parentContextKey" parameter is sufficient in this case. |
| public static final String | LOCATOR_FACTORY_KEY_PARAM | Optional servlet context parameter (i.e., "parentContextKey")
used only when obtaining a parent context using the default implementation
of #loadParentContext(ServletContext servletContext) .
Specifies the 'factoryKey' used in the
BeanFactoryLocator#useBeanFactory(String factoryKey) method call,
obtaining the parent application context from the BeanFactoryLocator instance.
Supplying this "parentContextKey" parameter is sufficient when relying
on the default classpath*:beanRefContext.xml selector for
candidate factory references. |
| Method from org.springframework.web.context.ContextLoader Detail: |
public void closeWebApplicationContext(ServletContext servletContext) {
servletContext.log("Closing Spring root WebApplicationContext");
try {
if (this.context instanceof ConfigurableWebApplicationContext) {
((ConfigurableWebApplicationContext) this.context).close();
}
}
finally {
currentContextPerThread.remove(Thread.currentThread().getContextClassLoader());
servletContext.removeAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
if (this.parentContextRef != null) {
this.parentContextRef.release();
}
}
}
Close Spring's web application context for the given servlet context. If
the default #loadParentContext(ServletContext) implementation,
which uses ContextSingletonBeanFactoryLocator, has loaded any shared
parent context, release one reference to that shared parent context.
If overriding #loadParentContext(ServletContext) , you may have
to override this method as well. |
protected WebApplicationContext createWebApplicationContext(ServletContext servletContext,
ApplicationContext parent) throws BeansException {
Class contextClass = determineContextClass(servletContext);
if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
throw new ApplicationContextException("Custom context class [" + contextClass.getName() +
"] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");
}
ConfigurableWebApplicationContext wac =
(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
wac.setParent(parent);
wac.setServletContext(servletContext);
wac.setConfigLocation(servletContext.getInitParameter(CONFIG_LOCATION_PARAM));
customizeContext(servletContext, wac);
wac.refresh();
return wac;
}
Instantiate the root WebApplicationContext for this loader, either the
default context class or a custom context class if specified.
This implementation expects custom contexts to implement the
ConfigurableWebApplicationContext interface.
Can be overridden in subclasses.
In addition, #customizeContext gets called prior to refreshing the
context, allowing subclasses to perform custom modifications to the context. |
protected void customizeContext(ServletContext servletContext,
ConfigurableWebApplicationContext applicationContext) {
}
Customize the ConfigurableWebApplicationContext created by this
ContextLoader after config locations have been supplied to the context
but before the context is refreshed.
The default implementation is empty but can be overridden in subclasses
to customize the application context. |
protected Class determineContextClass(ServletContext servletContext) throws ApplicationContextException {
String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);
if (contextClassName != null) {
try {
return ClassUtils.forName(contextClassName);
}
catch (ClassNotFoundException ex) {
throw new ApplicationContextException(
"Failed to load custom context class [" + contextClassName + "]", ex);
}
}
else {
contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
try {
return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());
}
catch (ClassNotFoundException ex) {
throw new ApplicationContextException(
"Failed to load default context class [" + contextClassName + "]", ex);
}
}
}
Return the WebApplicationContext implementation class to use, either the
default XmlWebApplicationContext or a custom context class if specified. |
public static WebApplicationContext getCurrentWebApplicationContext() {
return (WebApplicationContext) currentContextPerThread.get(Thread.currentThread().getContextClassLoader());
}
Obtain the Spring root web application context for the current thread
(i.e. for the current thread's context ClassLoader, which needs to be
the web application's ClassLoader). |
public WebApplicationContext initWebApplicationContext(ServletContext servletContext) throws IllegalStateException, BeansException {
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!");
}
servletContext.log("Initializing Spring root WebApplicationContext");
if (logger.isInfoEnabled()) {
logger.info("Root WebApplicationContext: initialization started");
}
long startTime = System.currentTimeMillis();
try {
// Determine parent for root web application context, if any.
ApplicationContext parent = loadParentContext(servletContext);
// Store context in local instance variable, to guarantee that
// it is available on 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("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;
}
}
|
protected ApplicationContext loadParentContext(ServletContext servletContext) throws BeansException {
ApplicationContext parentContext = null;
String locatorFactorySelector = servletContext.getInitParameter(LOCATOR_FACTORY_SELECTOR_PARAM);
String parentContextKey = servletContext.getInitParameter(LOCATOR_FACTORY_KEY_PARAM);
if (parentContextKey != null) {
// locatorFactorySelector may be null, indicating the default "classpath*:beanRefContext.xml"
BeanFactoryLocator locator = ContextSingletonBeanFactoryLocator.getInstance(locatorFactorySelector);
if (logger.isDebugEnabled()) {
logger.debug("Getting parent context definition: using parent context key of '" +
parentContextKey + "' with BeanFactoryLocator");
}
this.parentContextRef = locator.useBeanFactory(parentContextKey);
parentContext = (ApplicationContext) this.parentContextRef.getFactory();
}
return parentContext;
}
Template method with default implementation (which may be overridden by a
subclass), to load or obtain an ApplicationContext instance which will be
used as the parent context of the root WebApplicationContext. If the
return value from the method is null, no parent context is set.
The main reason to load a parent context here is to allow multiple root
web application contexts to all be children of a shared EAR context, or
alternately to also share the same parent context that is visible to
EJBs. For pure web applications, there is usually no need to worry about
having a parent context to the root web application context.
The default implementation uses
org.springframework.context.access.ContextSingletonBeanFactoryLocator ,
configured via #LOCATOR_FACTORY_SELECTOR_PARAM and
#LOCATOR_FACTORY_KEY_PARAM , to load a parent context
which will be shared by all other users of ContextsingletonBeanFactoryLocator
which also use the same configuration parameters. |