diff --git a/org.springframework.context/src/main/java/org/springframework/context/ApplicationContextInitializer.java b/org.springframework.context/src/main/java/org/springframework/context/ApplicationContextInitializer.java index 3ec99452410..aa50b4cc3a8 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/ApplicationContextInitializer.java +++ b/org.springframework.context/src/main/java/org/springframework/context/ApplicationContextInitializer.java @@ -20,6 +20,12 @@ package org.springframework.context; * Callback interface for initializing a Spring {@link ConfigurableApplicationContext} * prior to being {@linkplain ConfigurableApplicationContext#refresh() refreshed}. * + *
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. + * *
{@code ApplicationContextInitializer} processors are encouraged to detect
* whether Spring's {@link org.springframework.core.Ordered Ordered} or
* {@link org.springframework.core.PriorityOrdered PriorityOrdered} interfaces are also
@@ -29,6 +35,8 @@ package org.springframework.context;
* @since 3.1
* @see org.springframework.web.context.ContextLoader#customizeContext
* @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 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.
+ *
* Passes a "contextConfigLocation" servlet init-param to the context instance,
* parsing it into potentially multiple file paths which can be separated by any
* 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 Juergen Hoeller
* @author Sam Brannen
+ * @author Chris Beams
* @see #doService
* @see #setContextClass
* @see #setContextConfigLocation
+ * @see #setContextInitializerClasses
* @see #setNamespace
*/
@SuppressWarnings("serial")
@@ -117,6 +132,12 @@ public abstract class FrameworkServlet extends HttpServletBean {
*/
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 */
private String contextAttribute;
@@ -151,6 +172,8 @@ public abstract class FrameworkServlet extends HttpServletBean {
/** Flag used to detect whether onRefresh has already been called */
private boolean refreshEventReceived = false;
+ private String contextInitializerClasses;
+
/**
* 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);
}
+ /**
+ * 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
* 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()));
postProcessWebApplicationContext(wac);
+
+ initializeWebApplicationContext(wac);
+
wac.refresh();
return wac;
@@ -460,14 +495,50 @@ public abstract class FrameworkServlet extends HttpServletBean {
protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
return createWebApplicationContext((ApplicationContext) parent);
}
-
+
+ /**
+ * Delegate the WebApplicationContext before it is refreshed to any
+ * {@link ApplicationContextInitializer} instances specified by the
+ * "contextInitializerClasses" servlet init-param.
+ * 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 The default implementation is empty. 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)
* @see #createWebApplicationContext
+ * @see #initializeWebApplicationContext
* @see ConfigurableWebApplicationContext#refresh()
*/
protected void postProcessWebApplicationContext(ConfigurableWebApplicationContext wac) {
refresh() will
* be called automatically after this method returns.
+ *