Support "contextInitializerClasses" init-param
FrameworkServlet now has support equivalent to ContextLoader and its "contextInitializerClasses" context-param introduced in 3.1 M1. This allows users to specify ApplicationContextInitializers at the root (ContextLoader) level and/or at the DispatcherServlet level. Issue: SPR-8366
This commit is contained in:
parent
3c6254df90
commit
56720fc42c
|
|
@ -20,6 +20,12 @@ package org.springframework.context;
|
||||||
* Callback interface for initializing a Spring {@link ConfigurableApplicationContext}
|
* Callback interface for initializing a Spring {@link ConfigurableApplicationContext}
|
||||||
* prior to being {@linkplain ConfigurableApplicationContext#refresh() refreshed}.
|
* prior to being {@linkplain ConfigurableApplicationContext#refresh() refreshed}.
|
||||||
*
|
*
|
||||||
|
* <p>Typically used within web applications that require some programmatic initialization
|
||||||
|
* of the application context. For example, registering property sources or activating
|
||||||
|
* profiles against the {@linkplain ConfigurableApplicationContext#getEnvironment()
|
||||||
|
* context's environment}. See {@code ContextLoader} and {@code FrameworkServlet} support
|
||||||
|
* for declaring a "contextInitializerClasses" context-param and init-param, respectively.
|
||||||
|
*
|
||||||
* <p>{@code ApplicationContextInitializer} processors are encouraged to detect
|
* <p>{@code ApplicationContextInitializer} processors are encouraged to detect
|
||||||
* whether Spring's {@link org.springframework.core.Ordered Ordered} or
|
* whether Spring's {@link org.springframework.core.Ordered Ordered} or
|
||||||
* {@link org.springframework.core.PriorityOrdered PriorityOrdered} interfaces are also
|
* {@link org.springframework.core.PriorityOrdered PriorityOrdered} interfaces are also
|
||||||
|
|
@ -29,6 +35,8 @@ package org.springframework.context;
|
||||||
* @since 3.1
|
* @since 3.1
|
||||||
* @see org.springframework.web.context.ContextLoader#customizeContext
|
* @see org.springframework.web.context.ContextLoader#customizeContext
|
||||||
* @see org.springframework.web.context.ContextLoader#CONTEXT_INITIALIZER_CLASSES_PARAM
|
* @see org.springframework.web.context.ContextLoader#CONTEXT_INITIALIZER_CLASSES_PARAM
|
||||||
|
* @see org.springframework.web.servlet.FrameworkServlet#setContextInitializerClasses
|
||||||
|
* @see org.springframework.web.servlet.FrameworkServlet#initializeWebApplicationContext
|
||||||
*/
|
*/
|
||||||
public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {
|
public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import javax.servlet.http.HttpServletResponse;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ApplicationContextException;
|
import org.springframework.context.ApplicationContextException;
|
||||||
|
import org.springframework.context.ApplicationContextInitializer;
|
||||||
import org.springframework.context.ApplicationListener;
|
import org.springframework.context.ApplicationListener;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.context.event.ContextRefreshedEvent;
|
import org.springframework.context.event.ContextRefreshedEvent;
|
||||||
|
|
@ -34,6 +35,8 @@ import org.springframework.context.event.SourceFilteringListener;
|
||||||
import org.springframework.context.i18n.LocaleContext;
|
import org.springframework.context.i18n.LocaleContext;
|
||||||
import org.springframework.context.i18n.LocaleContextHolder;
|
import org.springframework.context.i18n.LocaleContextHolder;
|
||||||
import org.springframework.context.i18n.SimpleLocaleContext;
|
import org.springframework.context.i18n.SimpleLocaleContext;
|
||||||
|
import org.springframework.util.ClassUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.context.ConfigurableWebApplicationContext;
|
import org.springframework.web.context.ConfigurableWebApplicationContext;
|
||||||
import org.springframework.web.context.WebApplicationContext;
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
import org.springframework.web.context.request.RequestAttributes;
|
import org.springframework.web.context.request.RequestAttributes;
|
||||||
|
|
@ -71,6 +74,16 @@ import org.springframework.web.util.WebUtils;
|
||||||
* {@link org.springframework.web.context.ConfigurableWebApplicationContext
|
* {@link org.springframework.web.context.ConfigurableWebApplicationContext
|
||||||
* ConfigurableWebApplicationContext} SPI.
|
* ConfigurableWebApplicationContext} SPI.
|
||||||
*
|
*
|
||||||
|
* <p>Accepts an optional "contextInitializerClasses" servlet init-param that
|
||||||
|
* specifies one or more {@link org.springframework.context.ApplicationContextInitializer
|
||||||
|
* ApplicationContextInitializer} classes. The managed web application context will be
|
||||||
|
* delegated to these initializers, allowing for additional programmatic configuration,
|
||||||
|
* e.g. adding property sources or activating profiles against the {@linkplain
|
||||||
|
* org.springframework.context.ConfigurableApplicationContext#getEnvironment() context's
|
||||||
|
* environment}. See also {@link org.springframework.web.context.ContextLoader} which
|
||||||
|
* supports a "contextInitializerClasses" context-param with identical semantics for
|
||||||
|
* the "root" web application context.
|
||||||
|
*
|
||||||
* <p>Passes a "contextConfigLocation" servlet init-param to the context instance,
|
* <p>Passes a "contextConfigLocation" servlet init-param to the context instance,
|
||||||
* parsing it into potentially multiple file paths which can be separated by any
|
* parsing it into potentially multiple file paths which can be separated by any
|
||||||
* number of commas and spaces, like "test-servlet.xml, myServlet.xml".
|
* number of commas and spaces, like "test-servlet.xml, myServlet.xml".
|
||||||
|
|
@ -90,9 +103,11 @@ import org.springframework.web.util.WebUtils;
|
||||||
* @author Rod Johnson
|
* @author Rod Johnson
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @author Sam Brannen
|
* @author Sam Brannen
|
||||||
|
* @author Chris Beams
|
||||||
* @see #doService
|
* @see #doService
|
||||||
* @see #setContextClass
|
* @see #setContextClass
|
||||||
* @see #setContextConfigLocation
|
* @see #setContextConfigLocation
|
||||||
|
* @see #setContextInitializerClasses
|
||||||
* @see #setNamespace
|
* @see #setNamespace
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
|
|
@ -117,6 +132,12 @@ public abstract class FrameworkServlet extends HttpServletBean {
|
||||||
*/
|
*/
|
||||||
public static final String SERVLET_CONTEXT_PREFIX = FrameworkServlet.class.getName() + ".CONTEXT.";
|
public static final String SERVLET_CONTEXT_PREFIX = FrameworkServlet.class.getName() + ".CONTEXT.";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Any number of these characters are considered delimiters between
|
||||||
|
* multiple values in a single init-param String value.
|
||||||
|
* @see #initializeWebApplicationContext
|
||||||
|
*/
|
||||||
|
private String INIT_PARAM_DELIMITERS = ",; \t\n";
|
||||||
|
|
||||||
/** ServletContext attribute to find the WebApplicationContext in */
|
/** ServletContext attribute to find the WebApplicationContext in */
|
||||||
private String contextAttribute;
|
private String contextAttribute;
|
||||||
|
|
@ -151,6 +172,8 @@ public abstract class FrameworkServlet extends HttpServletBean {
|
||||||
/** Flag used to detect whether onRefresh has already been called */
|
/** Flag used to detect whether onRefresh has already been called */
|
||||||
private boolean refreshEventReceived = false;
|
private boolean refreshEventReceived = false;
|
||||||
|
|
||||||
|
private String contextInitializerClasses;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the name of the ServletContext attribute which should be used to retrieve the
|
* Set the name of the ServletContext attribute which should be used to retrieve the
|
||||||
|
|
@ -204,6 +227,15 @@ public abstract class FrameworkServlet extends HttpServletBean {
|
||||||
return (this.namespace != null ? this.namespace : getServletName() + DEFAULT_NAMESPACE_SUFFIX);
|
return (this.namespace != null ? this.namespace : getServletName() + DEFAULT_NAMESPACE_SUFFIX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify the set of fully-qualified {@link ApplicationContextInitializer} class
|
||||||
|
* names, per the optional "contextInitializerClasses" servlet init-param.
|
||||||
|
* @see #createWebApplicationContext
|
||||||
|
*/
|
||||||
|
public void setContextInitializerClasses(String contextInitializerClasses) {
|
||||||
|
this.contextInitializerClasses = contextInitializerClasses;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the context config location explicitly, instead of relying on the default
|
* Set the context config location explicitly, instead of relying on the default
|
||||||
* location built from the namespace. This location string can consist of
|
* location built from the namespace. This location string can consist of
|
||||||
|
|
@ -442,6 +474,9 @@ public abstract class FrameworkServlet extends HttpServletBean {
|
||||||
wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener()));
|
wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener()));
|
||||||
|
|
||||||
postProcessWebApplicationContext(wac);
|
postProcessWebApplicationContext(wac);
|
||||||
|
|
||||||
|
initializeWebApplicationContext(wac);
|
||||||
|
|
||||||
wac.refresh();
|
wac.refresh();
|
||||||
|
|
||||||
return wac;
|
return wac;
|
||||||
|
|
@ -461,13 +496,49 @@ public abstract class FrameworkServlet extends HttpServletBean {
|
||||||
return createWebApplicationContext((ApplicationContext) parent);
|
return createWebApplicationContext((ApplicationContext) parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delegate the WebApplicationContext before it is refreshed to any
|
||||||
|
* {@link ApplicationContextInitializer} instances specified by the
|
||||||
|
* "contextInitializerClasses" servlet init-param.
|
||||||
|
* <p>See also {@link #postProcessWebApplicationContext}, which is designed to allow
|
||||||
|
* subclasses (as opposed to end-users) to modify the application context, and is
|
||||||
|
* called immediately after this method.
|
||||||
|
* @param wac the configured WebApplicationContext (not refreshed yet)
|
||||||
|
* @see #createWebApplicationContext
|
||||||
|
* @see #postProcessWebApplicationContext
|
||||||
|
* @see ConfigurableWebApplicationContext#refresh()
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected void initializeWebApplicationContext(ConfigurableWebApplicationContext wac) {
|
||||||
|
if (this.contextInitializerClasses != null) {
|
||||||
|
String[] initializerClassNames = StringUtils.tokenizeToStringArray(this.contextInitializerClasses, INIT_PARAM_DELIMITERS);
|
||||||
|
for(String initializerClassName : initializerClassNames) {
|
||||||
|
ApplicationContextInitializer<ConfigurableApplicationContext> initializer = null;
|
||||||
|
try {
|
||||||
|
Class<?> initializerClass = ClassUtils.forName(initializerClassName, wac.getClassLoader());
|
||||||
|
initializer = BeanUtils.instantiateClass(initializerClass, ApplicationContextInitializer.class);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
String.format("Could not instantiate class [%s] specified via " +
|
||||||
|
"'contextInitializerClasses' init-param", initializerClassName), ex);
|
||||||
|
}
|
||||||
|
initializer.initialize(wac);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Post-process the given WebApplicationContext before it is refreshed
|
* Post-process the given WebApplicationContext before it is refreshed
|
||||||
* and activated as context for this servlet.
|
* and activated as context for this servlet.
|
||||||
* <p>The default implementation is empty. <code>refresh()</code> will
|
* <p>The default implementation is empty. <code>refresh()</code> will
|
||||||
* be called automatically after this method returns.
|
* be called automatically after this method returns.
|
||||||
|
* <p>Note that this method is designed to allow subclasses to modify the application
|
||||||
|
* context, while {@link #initializeWebApplicationContext} is designed to allow
|
||||||
|
* end-users to modify the context through the use of
|
||||||
|
* {@link ApplicationContextInitializer}s.
|
||||||
* @param wac the configured WebApplicationContext (not refreshed yet)
|
* @param wac the configured WebApplicationContext (not refreshed yet)
|
||||||
* @see #createWebApplicationContext
|
* @see #createWebApplicationContext
|
||||||
|
* @see #initializeWebApplicationContext
|
||||||
* @see ConfigurableWebApplicationContext#refresh()
|
* @see ConfigurableWebApplicationContext#refresh()
|
||||||
*/
|
*/
|
||||||
protected void postProcessWebApplicationContext(ConfigurableWebApplicationContext wac) {
|
protected void postProcessWebApplicationContext(ConfigurableWebApplicationContext wac) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue