Introduced "globalInitializerClasses" next to the existing "contextInitializerClasses", applying to FrameworkServlets as well
Issue: SPR-11314
(cherry picked from commit 91881ff
)
This commit is contained in:
parent
52c11eab41
commit
5fb2665d1c
|
@ -18,7 +18,6 @@ package org.springframework.web.context;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
@ -78,8 +77,8 @@ import org.springframework.util.StringUtils;
|
|||
*
|
||||
* <p>As of Spring 3.1, {@code ContextLoader} supports injecting the root web
|
||||
* application context via the {@link #ContextLoader(WebApplicationContext)}
|
||||
* constructor, allowing for programmatic configuration in Servlet 3.0+ environments. See
|
||||
* {@link org.springframework.web.WebApplicationInitializer} for usage examples.
|
||||
* constructor, allowing for programmatic configuration in Servlet 3.0+ environments.
|
||||
* See {@link org.springframework.web.WebApplicationInitializer} for usage examples.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Colin Sampaleanu
|
||||
|
@ -91,26 +90,12 @@ import org.springframework.util.StringUtils;
|
|||
*/
|
||||
public class ContextLoader {
|
||||
|
||||
/**
|
||||
* Config param for the root WebApplicationContext implementation class to use: {@value}
|
||||
* @see #determineContextClass(ServletContext)
|
||||
* @see #createWebApplicationContext(ServletContext, ApplicationContext)
|
||||
*/
|
||||
public static final String CONTEXT_CLASS_PARAM = "contextClass";
|
||||
|
||||
/**
|
||||
* Config param for the root WebApplicationContext id,
|
||||
* to be used as serialization id for the underlying BeanFactory: {@value}
|
||||
*/
|
||||
public static final String CONTEXT_ID_PARAM = "contextId";
|
||||
|
||||
/**
|
||||
* Config param for which {@link ApplicationContextInitializer} classes to use
|
||||
* for initializing the web application context: {@value}
|
||||
* @see #customizeContext(ServletContext, ConfigurableWebApplicationContext)
|
||||
*/
|
||||
public static final String CONTEXT_INITIALIZER_CLASSES_PARAM = "contextInitializerClasses";
|
||||
|
||||
/**
|
||||
* Name of servlet context parameter (i.e., {@value}) that can specify the
|
||||
* config location for the root context, falling back to the implementation's
|
||||
|
@ -119,6 +104,27 @@ public class ContextLoader {
|
|||
*/
|
||||
public static final String CONFIG_LOCATION_PARAM = "contextConfigLocation";
|
||||
|
||||
/**
|
||||
* Config param for the root WebApplicationContext implementation class to use: {@value}
|
||||
* @see #determineContextClass(ServletContext)
|
||||
* @see #createWebApplicationContext(ServletContext, ApplicationContext)
|
||||
*/
|
||||
public static final String CONTEXT_CLASS_PARAM = "contextClass";
|
||||
|
||||
/**
|
||||
* Config param for {@link ApplicationContextInitializer} classes to use
|
||||
* for initializing the root web application context: {@value}
|
||||
* @see #customizeContext(ServletContext, ConfigurableWebApplicationContext)
|
||||
*/
|
||||
public static final String CONTEXT_INITIALIZER_CLASSES_PARAM = "contextInitializerClasses";
|
||||
|
||||
/**
|
||||
* Config param for global {@link ApplicationContextInitializer} classes to use
|
||||
* for initializing all web application contexts in the current application: {@value}
|
||||
* @see #customizeContext(ServletContext, ConfigurableWebApplicationContext)
|
||||
*/
|
||||
public static final String GLOBAL_INITIALIZER_CLASSES_PARAM = "globalInitializerClasses";
|
||||
|
||||
/**
|
||||
* Optional servlet context parameter (i.e., "{@code locatorFactorySelector}")
|
||||
* used only when obtaining a parent context using the default implementation
|
||||
|
@ -147,6 +153,12 @@ public class ContextLoader {
|
|||
*/
|
||||
public static final String LOCATOR_FACTORY_KEY_PARAM = "parentContextKey";
|
||||
|
||||
/**
|
||||
* Any number of these characters are considered delimiters between
|
||||
* multiple values in a single init-param String value.
|
||||
*/
|
||||
private static final String INIT_PARAM_DELIMITERS = ",; \t\n";
|
||||
|
||||
/**
|
||||
* Name of the class path resource (relative to the ContextLoader class)
|
||||
* that defines ContextLoader's default strategy names.
|
||||
|
@ -381,14 +393,71 @@ public class ContextLoader {
|
|||
}
|
||||
|
||||
wac.setServletContext(sc);
|
||||
String initParameter = sc.getInitParameter(CONFIG_LOCATION_PARAM);
|
||||
if (initParameter != null) {
|
||||
wac.setConfigLocation(initParameter);
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* Customize the {@link ConfigurableWebApplicationContext} created by this
|
||||
* ContextLoader after config locations have been supplied to the context
|
||||
* but before the context is <em>refreshed</em>.
|
||||
* <p>The default implementation {@linkplain #determineContextInitializerClasses(ServletContext)
|
||||
* determines} what (if any) context initializer classes have been specified through
|
||||
* {@linkplain #CONTEXT_INITIALIZER_CLASSES_PARAM context init parameters} and
|
||||
* {@linkplain ApplicationContextInitializer#initialize invokes each} with the
|
||||
* given web application context.
|
||||
* <p>Any {@code ApplicationContextInitializers} implementing
|
||||
* {@link org.springframework.core.Ordered Ordered} or marked with @{@link
|
||||
* org.springframework.core.annotation.Order Order} will be sorted appropriately.
|
||||
* @param sc the current servlet context
|
||||
* @param wac the newly created application context
|
||||
* @see #createWebApplicationContext(ServletContext, ApplicationContext)
|
||||
* @see #CONTEXT_INITIALIZER_CLASSES_PARAM
|
||||
* @see ApplicationContextInitializer#initialize(ConfigurableApplicationContext)
|
||||
*/
|
||||
protected void customizeContext(ServletContext sc, ConfigurableWebApplicationContext wac) {
|
||||
List<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>> initializerClasses =
|
||||
determineContextInitializerClasses(sc);
|
||||
if (initializerClasses.isEmpty()) {
|
||||
// no ApplicationContextInitializers have been declared -> nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
ArrayList<ApplicationContextInitializer<ConfigurableApplicationContext>> initializerInstances =
|
||||
new ArrayList<ApplicationContextInitializer<ConfigurableApplicationContext>>();
|
||||
|
||||
for (Class<ApplicationContextInitializer<ConfigurableApplicationContext>> initializerClass : initializerClasses) {
|
||||
Class<?> initializerContextClass =
|
||||
GenericTypeResolver.resolveTypeArgument(initializerClass, ApplicationContextInitializer.class);
|
||||
if (initializerContextClass != null) {
|
||||
Assert.isAssignable(initializerContextClass, wac.getClass(), String.format(
|
||||
"Could not add context initializer [%s] since its generic parameter [%s] " +
|
||||
"is not assignable from the type of application context used by this " +
|
||||
"context loader [%s]: ", initializerClass.getName(), initializerContextClass.getName(),
|
||||
wac.getClass().getName()));
|
||||
}
|
||||
initializerInstances.add(BeanUtils.instantiateClass(initializerClass));
|
||||
}
|
||||
|
||||
AnnotationAwareOrderComparator.sort(initializerInstances);
|
||||
for (ApplicationContextInitializer<ConfigurableApplicationContext> initializer : initializerInstances) {
|
||||
initializer.initialize(wac);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the WebApplicationContext implementation class to use, either the
|
||||
* default XmlWebApplicationContext or a custom context class if specified.
|
||||
|
@ -426,80 +495,38 @@ public class ContextLoader {
|
|||
* @param servletContext current servlet context
|
||||
* @see #CONTEXT_INITIALIZER_CLASSES_PARAM
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>>
|
||||
determineContextInitializerClasses(ServletContext servletContext) {
|
||||
String classNames = servletContext.getInitParameter(CONTEXT_INITIALIZER_CLASSES_PARAM);
|
||||
|
||||
List<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>> classes =
|
||||
new ArrayList<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>>();
|
||||
if (classNames != null) {
|
||||
for (String className : StringUtils.tokenizeToStringArray(classNames, ",")) {
|
||||
try {
|
||||
Class<?> clazz = ClassUtils.forName(className, ClassUtils.getDefaultClassLoader());
|
||||
Assert.isAssignable(ApplicationContextInitializer.class, clazz,
|
||||
"class [" + className + "] must implement ApplicationContextInitializer");
|
||||
classes.add((Class<ApplicationContextInitializer<ConfigurableApplicationContext>>)clazz);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
throw new ApplicationContextException(
|
||||
"Failed to load context initializer class [" + className + "]", ex);
|
||||
}
|
||||
new ArrayList<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>>();
|
||||
|
||||
String globalClassNames = servletContext.getInitParameter(GLOBAL_INITIALIZER_CLASSES_PARAM);
|
||||
if (globalClassNames != null) {
|
||||
for (String className : StringUtils.tokenizeToStringArray(globalClassNames, INIT_PARAM_DELIMITERS)) {
|
||||
classes.add(loadInitializerClass(className));
|
||||
}
|
||||
}
|
||||
|
||||
String localClassNames = servletContext.getInitParameter(CONTEXT_INITIALIZER_CLASSES_PARAM);
|
||||
if (localClassNames != null) {
|
||||
for (String className : StringUtils.tokenizeToStringArray(localClassNames, INIT_PARAM_DELIMITERS)) {
|
||||
classes.add(loadInitializerClass(className));
|
||||
}
|
||||
}
|
||||
|
||||
return classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Customize the {@link ConfigurableWebApplicationContext} created by this
|
||||
* ContextLoader after config locations have been supplied to the context
|
||||
* but before the context is <em>refreshed</em>.
|
||||
* <p>The default implementation {@linkplain #determineContextInitializerClasses(ServletContext)
|
||||
* determines} what (if any) context initializer classes have been specified through
|
||||
* {@linkplain #CONTEXT_INITIALIZER_CLASSES_PARAM context init parameters} and
|
||||
* {@linkplain ApplicationContextInitializer#initialize invokes each} with the
|
||||
* given web application context.
|
||||
* <p>Any {@code ApplicationContextInitializers} implementing
|
||||
* {@link org.springframework.core.Ordered Ordered} or marked with @{@link
|
||||
* org.springframework.core.annotation.Order Order} will be sorted appropriately.
|
||||
* @param servletContext the current servlet context
|
||||
* @param applicationContext the newly created application context
|
||||
* @see #createWebApplicationContext(ServletContext, ApplicationContext)
|
||||
* @see #CONTEXT_INITIALIZER_CLASSES_PARAM
|
||||
* @see ApplicationContextInitializer#initialize(ConfigurableApplicationContext)
|
||||
*/
|
||||
protected void customizeContext(ServletContext servletContext, ConfigurableWebApplicationContext applicationContext) {
|
||||
List<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>> initializerClasses =
|
||||
determineContextInitializerClasses(servletContext);
|
||||
if (initializerClasses.size() == 0) {
|
||||
// no ApplicationContextInitializers have been declared -> nothing to do
|
||||
return;
|
||||
@SuppressWarnings("unchecked")
|
||||
private Class<ApplicationContextInitializer<ConfigurableApplicationContext>> loadInitializerClass(String className) {
|
||||
try {
|
||||
Class<?> clazz = ClassUtils.forName(className, ClassUtils.getDefaultClassLoader());
|
||||
Assert.isAssignable(ApplicationContextInitializer.class, clazz);
|
||||
return (Class<ApplicationContextInitializer<ConfigurableApplicationContext>>) clazz;
|
||||
}
|
||||
|
||||
Class<?> contextClass = applicationContext.getClass();
|
||||
ArrayList<ApplicationContextInitializer<ConfigurableApplicationContext>> initializerInstances =
|
||||
new ArrayList<ApplicationContextInitializer<ConfigurableApplicationContext>>();
|
||||
|
||||
for (Class<ApplicationContextInitializer<ConfigurableApplicationContext>> initializerClass : initializerClasses) {
|
||||
Class<?> initializerContextClass =
|
||||
GenericTypeResolver.resolveTypeArgument(initializerClass, ApplicationContextInitializer.class);
|
||||
if (initializerContextClass != null) {
|
||||
Assert.isAssignable(initializerContextClass, contextClass, String.format(
|
||||
"Could not add context initializer [%s] as its generic parameter [%s] " +
|
||||
"is not assignable from the type of application context used by this " +
|
||||
"context loader [%s]: ", initializerClass.getName(), initializerContextClass.getName(),
|
||||
contextClass.getName()));
|
||||
}
|
||||
initializerInstances.add(BeanUtils.instantiateClass(initializerClass));
|
||||
}
|
||||
|
||||
ConfigurableEnvironment env = applicationContext.getEnvironment();
|
||||
if (env instanceof ConfigurableWebEnvironment) {
|
||||
((ConfigurableWebEnvironment)env).initPropertySources(servletContext, null);
|
||||
}
|
||||
|
||||
Collections.sort(initializerInstances, new AnnotationAwareOrderComparator());
|
||||
for (ApplicationContextInitializer<ConfigurableApplicationContext> initializer : initializerInstances) {
|
||||
initializer.initialize(applicationContext);
|
||||
catch (ClassNotFoundException ex) {
|
||||
throw new ApplicationContextException("Failed to load context initializer class [" + className + "]", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ package org.springframework.web.servlet;
|
|||
import java.io.IOException;
|
||||
import java.security.Principal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.Callable;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
|
@ -38,14 +37,17 @@ import org.springframework.context.event.SourceFilteringListener;
|
|||
import org.springframework.context.i18n.LocaleContext;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.context.i18n.SimpleLocaleContext;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.context.ConfigurableWebApplicationContext;
|
||||
import org.springframework.web.context.ConfigurableWebEnvironment;
|
||||
import org.springframework.web.context.ContextLoader;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
|
@ -172,6 +174,13 @@ public abstract class FrameworkServlet extends HttpServletBean {
|
|||
/** Explicit context config location */
|
||||
private String contextConfigLocation;
|
||||
|
||||
/** Actual ApplicationContextInitializer instances to apply to the context */
|
||||
private final ArrayList<ApplicationContextInitializer<ConfigurableApplicationContext>> contextInitializers =
|
||||
new ArrayList<ApplicationContextInitializer<ConfigurableApplicationContext>>();
|
||||
|
||||
/** Comma-delimited ApplicationContextInitializer class names set through init param */
|
||||
private String contextInitializerClasses;
|
||||
|
||||
/** Should we publish the context as a ServletContext attribute? */
|
||||
private boolean publishContext = true;
|
||||
|
||||
|
@ -193,13 +202,6 @@ public abstract class FrameworkServlet extends HttpServletBean {
|
|||
/** Flag used to detect whether onRefresh has already been called */
|
||||
private boolean refreshEventReceived = false;
|
||||
|
||||
/** Comma-delimited ApplicationContextInitializer classnames set through init param */
|
||||
private String contextInitializerClasses;
|
||||
|
||||
/** Actual ApplicationContextInitializer instances to apply to the context */
|
||||
private ArrayList<ApplicationContextInitializer<ConfigurableApplicationContext>> contextInitializers =
|
||||
new ArrayList<ApplicationContextInitializer<ConfigurableApplicationContext>>();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@code FrameworkServlet} that will create its own internal web
|
||||
|
@ -333,28 +335,6 @@ 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 #configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext)
|
||||
* @see #applyInitializers(ConfigurableApplicationContext)
|
||||
*/
|
||||
public void setContextInitializerClasses(String contextInitializerClasses) {
|
||||
this.contextInitializerClasses = contextInitializerClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify which {@link ApplicationContextInitializer} instances should be used
|
||||
* to initialize the application context used by this {@code FrameworkServlet}.
|
||||
* @see #configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext)
|
||||
* @see #applyInitializers(ConfigurableApplicationContext)
|
||||
*/
|
||||
public void setContextInitializers(ApplicationContextInitializer<ConfigurableApplicationContext>... contextInitializers) {
|
||||
for (ApplicationContextInitializer<ConfigurableApplicationContext> initializer : contextInitializers) {
|
||||
this.contextInitializers.add(initializer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the context config location explicitly, instead of relying on the default
|
||||
* location built from the namespace. This location string can consist of
|
||||
|
@ -371,6 +351,29 @@ public abstract class FrameworkServlet extends HttpServletBean {
|
|||
return this.contextConfigLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify which {@link ApplicationContextInitializer} instances should be used
|
||||
* to initialize the application context used by this {@code FrameworkServlet}.
|
||||
* @see #configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext)
|
||||
* @see #applyInitializers(ConfigurableApplicationContext)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setContextInitializers(ApplicationContextInitializer<? extends ConfigurableApplicationContext>... contextInitializers) {
|
||||
for (ApplicationContextInitializer<? extends ConfigurableApplicationContext> initializer : contextInitializers) {
|
||||
this.contextInitializers.add((ApplicationContextInitializer<ConfigurableApplicationContext>) initializer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the set of fully-qualified {@link ApplicationContextInitializer} class
|
||||
* names, per the optional "contextInitializerClasses" servlet init-param.
|
||||
* @see #configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext)
|
||||
* @see #applyInitializers(ConfigurableApplicationContext)
|
||||
*/
|
||||
public void setContextInitializerClasses(String contextInitializerClasses) {
|
||||
this.contextInitializerClasses = contextInitializerClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to publish this servlet's context as a ServletContext attribute,
|
||||
* available to all objects in the web container. Default is "true".
|
||||
|
@ -635,19 +638,16 @@ public abstract class FrameworkServlet extends HttpServletBean {
|
|||
wac.setNamespace(getNamespace());
|
||||
wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener()));
|
||||
|
||||
// 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
|
||||
// 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(getServletContext(), getServletConfig());
|
||||
((ConfigurableWebEnvironment) env).initPropertySources(getServletContext(), getServletConfig());
|
||||
}
|
||||
|
||||
postProcessWebApplicationContext(wac);
|
||||
|
||||
applyInitializers(wac);
|
||||
|
||||
wac.refresh();
|
||||
}
|
||||
|
||||
|
@ -665,43 +665,6 @@ public abstract class FrameworkServlet extends HttpServletBean {
|
|||
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 ConfigurableApplicationContext#refresh()
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void applyInitializers(ConfigurableApplicationContext wac) {
|
||||
if (this.contextInitializerClasses != null) {
|
||||
String[] initializerClassNames =
|
||||
StringUtils.tokenizeToStringArray(this.contextInitializerClasses, INIT_PARAM_DELIMITERS);
|
||||
for (String initializerClassName : initializerClassNames) {
|
||||
ApplicationContextInitializer<ConfigurableApplicationContext> initializer;
|
||||
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);
|
||||
}
|
||||
this.contextInitializers.add(initializer);
|
||||
}
|
||||
}
|
||||
Collections.sort(this.contextInitializers, new AnnotationAwareOrderComparator());
|
||||
for (ApplicationContextInitializer<ConfigurableApplicationContext> initializer : this.contextInitializers) {
|
||||
initializer.initialize(wac);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-process the given WebApplicationContext before it is refreshed
|
||||
* and activated as context for this servlet.
|
||||
|
@ -719,6 +682,60 @@ public abstract class FrameworkServlet extends HttpServletBean {
|
|||
protected void postProcessWebApplicationContext(ConfigurableWebApplicationContext wac) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 before this method.
|
||||
* @param wac the configured WebApplicationContext (not refreshed yet)
|
||||
* @see #createWebApplicationContext
|
||||
* @see #postProcessWebApplicationContext
|
||||
* @see ConfigurableApplicationContext#refresh()
|
||||
*/
|
||||
protected void applyInitializers(ConfigurableApplicationContext wac) {
|
||||
String globalClassNames = getServletContext().getInitParameter(ContextLoader.GLOBAL_INITIALIZER_CLASSES_PARAM);
|
||||
if (globalClassNames != null) {
|
||||
for (String className : StringUtils.tokenizeToStringArray(globalClassNames, INIT_PARAM_DELIMITERS)) {
|
||||
this.contextInitializers.add(loadInitializer(className, wac));
|
||||
}
|
||||
}
|
||||
|
||||
if (this.contextInitializerClasses != null) {
|
||||
for (String className : StringUtils.tokenizeToStringArray(this.contextInitializerClasses, INIT_PARAM_DELIMITERS)) {
|
||||
this.contextInitializers.add(loadInitializer(className, wac));
|
||||
}
|
||||
}
|
||||
|
||||
AnnotationAwareOrderComparator.sort(this.contextInitializers);
|
||||
for (ApplicationContextInitializer<ConfigurableApplicationContext> initializer : this.contextInitializers) {
|
||||
initializer.initialize(wac);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private ApplicationContextInitializer<ConfigurableApplicationContext> loadInitializer(
|
||||
String className, ConfigurableApplicationContext wac) {
|
||||
try {
|
||||
Class<?> initializerClass = ClassUtils.forName(className, wac.getClassLoader());
|
||||
Class<?> initializerContextClass =
|
||||
GenericTypeResolver.resolveTypeArgument(initializerClass, ApplicationContextInitializer.class);
|
||||
if (initializerContextClass != null) {
|
||||
Assert.isAssignable(initializerContextClass, wac.getClass(), String.format(
|
||||
"Could not add context initializer [%s] since its generic parameter [%s] " +
|
||||
"is not assignable from the type of application context used by this " +
|
||||
"framework servlet [%s]: ", initializerClass.getName(), initializerContextClass.getName(),
|
||||
wac.getClass().getName()));
|
||||
}
|
||||
return BeanUtils.instantiateClass(initializerClass, ApplicationContextInitializer.class);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalArgumentException(String.format("Could not instantiate class [%s] specified " +
|
||||
"via 'contextInitializerClasses' init-param", className), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ServletContext attribute name for this servlet's WebApplicationContext.
|
||||
* <p>The default implementation returns
|
||||
|
|
|
@ -16,30 +16,17 @@
|
|||
|
||||
package org.springframework.web.context;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.tests.sample.beans.TestBean;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.tests.sample.beans.LifecycleBean;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextException;
|
||||
|
@ -50,11 +37,17 @@ import org.springframework.core.env.ConfigurableEnvironment;
|
|||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.mock.web.test.MockServletConfig;
|
||||
import org.springframework.mock.web.test.MockServletContext;
|
||||
import org.springframework.tests.sample.beans.LifecycleBean;
|
||||
import org.springframework.tests.sample.beans.TestBean;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.context.support.WebApplicationContextUtils;
|
||||
import org.springframework.web.context.support.XmlWebApplicationContext;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.springframework.web.servlet.SimpleWebApplicationContext;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Tests for {@link ContextLoader} and {@link ContextLoaderListener}.
|
||||
*
|
||||
|
@ -70,14 +63,14 @@ public final class ContextLoaderTests {
|
|||
public void testContextLoaderListenerWithDefaultContext() {
|
||||
MockServletContext sc = new MockServletContext("");
|
||||
sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM,
|
||||
"/org/springframework/web/context/WEB-INF/applicationContext.xml "
|
||||
+ "/org/springframework/web/context/WEB-INF/context-addition.xml");
|
||||
"/org/springframework/web/context/WEB-INF/applicationContext.xml " +
|
||||
"/org/springframework/web/context/WEB-INF/context-addition.xml");
|
||||
ServletContextListener listener = new ContextLoaderListener();
|
||||
ServletContextEvent event = new ServletContextEvent(sc);
|
||||
listener.contextInitialized(event);
|
||||
WebApplicationContext context = (WebApplicationContext) sc.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
|
||||
assertTrue("Correct WebApplicationContext exposed in ServletContext", context instanceof XmlWebApplicationContext);
|
||||
assertTrue(ContextLoader.getCurrentWebApplicationContext() instanceof XmlWebApplicationContext);
|
||||
assertTrue(WebApplicationContextUtils.getRequiredWebApplicationContext(sc) instanceof XmlWebApplicationContext);
|
||||
LifecycleBean lb = (LifecycleBean) context.getBean("lifecycle");
|
||||
assertTrue("Has father", context.containsBean("father"));
|
||||
assertTrue("Has rod", context.containsBean("rod"));
|
||||
|
@ -88,7 +81,7 @@ public final class ContextLoaderTests {
|
|||
listener.contextDestroyed(event);
|
||||
assertTrue("Destroyed", lb.isDestroyed());
|
||||
assertNull(sc.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE));
|
||||
assertNull(ContextLoader.getCurrentWebApplicationContext());
|
||||
assertNull(WebApplicationContextUtils.getWebApplicationContext(sc));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -104,12 +97,12 @@ public final class ContextLoaderTests {
|
|||
final MockServletContext sc = new MockServletContext("");
|
||||
sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM,
|
||||
"/org/springframework/web/context/WEB-INF/applicationContext.xml");
|
||||
final ServletContextListener listener = new ContextLoaderListener() {
|
||||
ServletContextListener listener = new ContextLoaderListener() {
|
||||
@Override
|
||||
protected void customizeContext(ServletContext servletContext, ConfigurableWebApplicationContext applicationContext) {
|
||||
assertNotNull("The ServletContext should not be null.", servletContext);
|
||||
assertEquals("Verifying that we received the expected ServletContext.", sc, servletContext);
|
||||
assertFalse("The ApplicationContext should not yet have been refreshed.", applicationContext.isActive());
|
||||
protected void customizeContext(ServletContext sc, ConfigurableWebApplicationContext wac) {
|
||||
assertNotNull("The ServletContext should not be null.", sc);
|
||||
assertEquals("Verifying that we received the expected ServletContext.", sc, sc);
|
||||
assertFalse("The ApplicationContext should not yet have been refreshed.", wac.isActive());
|
||||
buffer.append(expectedContents);
|
||||
}
|
||||
};
|
||||
|
@ -118,16 +111,45 @@ public final class ContextLoaderTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testContextLoaderListenerWithRegisteredContextInitializer() {
|
||||
public void testContextLoaderListenerWithLocalContextInitializers() {
|
||||
MockServletContext sc = new MockServletContext("");
|
||||
sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM,
|
||||
"org/springframework/web/context/WEB-INF/ContextLoaderTests-acc-context.xml");
|
||||
sc.addInitParameter(ContextLoader.CONTEXT_INITIALIZER_CLASSES_PARAM,
|
||||
StringUtils.arrayToCommaDelimitedString(
|
||||
new Object[]{TestContextInitializer.class.getName(), TestWebContextInitializer.class.getName()}));
|
||||
sc.addInitParameter(ContextLoader.CONTEXT_INITIALIZER_CLASSES_PARAM, StringUtils.arrayToCommaDelimitedString(
|
||||
new Object[] {TestContextInitializer.class.getName(), TestWebContextInitializer.class.getName()}));
|
||||
ContextLoaderListener listener = new ContextLoaderListener();
|
||||
listener.contextInitialized(new ServletContextEvent(sc));
|
||||
WebApplicationContext wac = ContextLoaderListener.getCurrentWebApplicationContext();
|
||||
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
|
||||
TestBean testBean = wac.getBean(TestBean.class);
|
||||
assertThat(testBean.getName(), equalTo("testName"));
|
||||
assertThat(wac.getServletContext().getAttribute("initialized"), notNullValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContextLoaderListenerWithGlobalContextInitializers() {
|
||||
MockServletContext sc = new MockServletContext("");
|
||||
sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM,
|
||||
"org/springframework/web/context/WEB-INF/ContextLoaderTests-acc-context.xml");
|
||||
sc.addInitParameter(ContextLoader.GLOBAL_INITIALIZER_CLASSES_PARAM, StringUtils.arrayToCommaDelimitedString(
|
||||
new Object[] {TestContextInitializer.class.getName(), TestWebContextInitializer.class.getName()}));
|
||||
ContextLoaderListener listener = new ContextLoaderListener();
|
||||
listener.contextInitialized(new ServletContextEvent(sc));
|
||||
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
|
||||
TestBean testBean = wac.getBean(TestBean.class);
|
||||
assertThat(testBean.getName(), equalTo("testName"));
|
||||
assertThat(wac.getServletContext().getAttribute("initialized"), notNullValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContextLoaderListenerWithMixedContextInitializers() {
|
||||
MockServletContext sc = new MockServletContext("");
|
||||
sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM,
|
||||
"org/springframework/web/context/WEB-INF/ContextLoaderTests-acc-context.xml");
|
||||
sc.addInitParameter(ContextLoader.CONTEXT_INITIALIZER_CLASSES_PARAM, TestContextInitializer.class.getName());
|
||||
sc.addInitParameter(ContextLoader.GLOBAL_INITIALIZER_CLASSES_PARAM, TestWebContextInitializer.class.getName());
|
||||
ContextLoaderListener listener = new ContextLoaderListener();
|
||||
listener.contextInitialized(new ServletContextEvent(sc));
|
||||
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
|
||||
TestBean testBean = wac.getBean(TestBean.class);
|
||||
assertThat(testBean.getName(), equalTo("testName"));
|
||||
assertThat(wac.getServletContext().getAttribute("initialized"), notNullValue());
|
||||
|
@ -136,7 +158,7 @@ public final class ContextLoaderTests {
|
|||
@Test
|
||||
public void testRegisteredContextInitializerCanAccessServletContextParamsViaEnvironment() {
|
||||
MockServletContext sc = new MockServletContext("");
|
||||
// config file doesn't matter. just a placeholder
|
||||
// config file doesn't matter - just a placeholder
|
||||
sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM,
|
||||
"/org/springframework/web/context/WEB-INF/empty-context.xml");
|
||||
|
||||
|
@ -153,12 +175,13 @@ public final class ContextLoaderTests {
|
|||
sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM,
|
||||
"/org/springframework/web/context/WEB-INF/empty-context.xml");
|
||||
sc.addInitParameter(ContextLoader.CONTEXT_INITIALIZER_CLASSES_PARAM,
|
||||
StringUtils.arrayToCommaDelimitedString(new Object[]{UnknownContextInitializer.class.getName()}));
|
||||
StringUtils.arrayToCommaDelimitedString(new Object[] {UnknownContextInitializer.class.getName()}));
|
||||
ContextLoaderListener listener = new ContextLoaderListener();
|
||||
try {
|
||||
listener.contextInitialized(new ServletContextEvent(sc));
|
||||
fail("expected exception");
|
||||
} catch (IllegalArgumentException ex) {
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
assertTrue(ex.getMessage().contains("not assignable"));
|
||||
}
|
||||
}
|
||||
|
@ -321,7 +344,9 @@ public final class ContextLoaderTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static class TestContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
|
||||
|
||||
@Override
|
||||
public void initialize(ConfigurableApplicationContext applicationContext) {
|
||||
ConfigurableEnvironment environment = applicationContext.getEnvironment();
|
||||
|
@ -334,7 +359,9 @@ public final class ContextLoaderTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static class TestWebContextInitializer implements ApplicationContextInitializer<ConfigurableWebApplicationContext> {
|
||||
|
||||
@Override
|
||||
public void initialize(ConfigurableWebApplicationContext applicationContext) {
|
||||
ServletContext ctx = applicationContext.getServletContext(); // type-safe access to servlet-specific methods
|
||||
|
@ -342,7 +369,9 @@ public final class ContextLoaderTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static class EnvApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableWebApplicationContext> {
|
||||
|
||||
@Override
|
||||
public void initialize(ConfigurableWebApplicationContext applicationContext) {
|
||||
// test that ApplicationContextInitializers can access ServletContext properties
|
||||
|
@ -352,11 +381,15 @@ public final class ContextLoaderTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static interface UnknownApplicationContext extends ConfigurableApplicationContext {
|
||||
|
||||
void unheardOf();
|
||||
}
|
||||
|
||||
|
||||
private static class UnknownContextInitializer implements ApplicationContextInitializer<UnknownApplicationContext> {
|
||||
|
||||
@Override
|
||||
public void initialize(UnknownApplicationContext applicationContext) {
|
||||
applicationContext.unheardOf();
|
||||
|
|
|
@ -18,7 +18,6 @@ package org.springframework.web.servlet;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletContext;
|
||||
|
@ -30,6 +29,7 @@ import junit.framework.TestCase;
|
|||
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.PropertyValue;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.support.DefaultMessageSourceResolvable;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
|
@ -40,7 +40,9 @@ import org.springframework.mock.web.test.MockServletConfig;
|
|||
import org.springframework.mock.web.test.MockServletContext;
|
||||
import org.springframework.tests.sample.beans.TestBean;
|
||||
import org.springframework.web.bind.EscapedErrors;
|
||||
import org.springframework.web.context.ConfigurableWebApplicationContext;
|
||||
import org.springframework.web.context.ConfigurableWebEnvironment;
|
||||
import org.springframework.web.context.ContextLoader;
|
||||
import org.springframework.web.context.ServletConfigAwareBean;
|
||||
import org.springframework.web.context.ServletContextAwareBean;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
@ -865,6 +867,46 @@ public class DispatcherServletTests extends TestCase {
|
|||
assertThat(response.getHeader("Allow"), equalTo("GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH"));
|
||||
}
|
||||
|
||||
public void testContextInitializers() throws Exception {
|
||||
DispatcherServlet servlet = new DispatcherServlet();
|
||||
servlet.setContextClass(SimpleWebApplicationContext.class);
|
||||
servlet.setContextInitializers(new TestWebContextInitializer(), new OtherWebContextInitializer());
|
||||
servlet.init(servletConfig);
|
||||
assertEquals("true", servletConfig.getServletContext().getAttribute("initialized"));
|
||||
assertEquals("true", servletConfig.getServletContext().getAttribute("otherInitialized"));
|
||||
}
|
||||
|
||||
public void testContextInitializerClasses() throws Exception {
|
||||
DispatcherServlet servlet = new DispatcherServlet();
|
||||
servlet.setContextClass(SimpleWebApplicationContext.class);
|
||||
servlet.setContextInitializerClasses(
|
||||
TestWebContextInitializer.class.getName() + "," + OtherWebContextInitializer.class.getName());
|
||||
servlet.init(servletConfig);
|
||||
assertEquals("true", servletConfig.getServletContext().getAttribute("initialized"));
|
||||
assertEquals("true", servletConfig.getServletContext().getAttribute("otherInitialized"));
|
||||
}
|
||||
|
||||
public void testGlobalInitializerClasses() throws Exception {
|
||||
DispatcherServlet servlet = new DispatcherServlet();
|
||||
servlet.setContextClass(SimpleWebApplicationContext.class);
|
||||
servletConfig.getServletContext().setInitParameter(ContextLoader.GLOBAL_INITIALIZER_CLASSES_PARAM,
|
||||
TestWebContextInitializer.class.getName() + "," + OtherWebContextInitializer.class.getName());
|
||||
servlet.init(servletConfig);
|
||||
assertEquals("true", servletConfig.getServletContext().getAttribute("initialized"));
|
||||
assertEquals("true", servletConfig.getServletContext().getAttribute("otherInitialized"));
|
||||
}
|
||||
|
||||
public void testMixedInitializerClasses() throws Exception {
|
||||
DispatcherServlet servlet = new DispatcherServlet();
|
||||
servlet.setContextClass(SimpleWebApplicationContext.class);
|
||||
servletConfig.getServletContext().setInitParameter(ContextLoader.GLOBAL_INITIALIZER_CLASSES_PARAM,
|
||||
TestWebContextInitializer.class.getName());
|
||||
servlet.setContextInitializerClasses(OtherWebContextInitializer.class.getName());
|
||||
servlet.init(servletConfig);
|
||||
assertEquals("true", servletConfig.getServletContext().getAttribute("initialized"));
|
||||
assertEquals("true", servletConfig.getServletContext().getAttribute("otherInitialized"));
|
||||
}
|
||||
|
||||
|
||||
public static class ControllerFromParent implements Controller {
|
||||
|
||||
|
@ -874,4 +916,22 @@ public class DispatcherServletTests extends TestCase {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static class TestWebContextInitializer implements ApplicationContextInitializer<ConfigurableWebApplicationContext> {
|
||||
|
||||
@Override
|
||||
public void initialize(ConfigurableWebApplicationContext applicationContext) {
|
||||
applicationContext.getServletContext().setAttribute("initialized", "true");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class OtherWebContextInitializer implements ApplicationContextInitializer<ConfigurableWebApplicationContext> {
|
||||
|
||||
@Override
|
||||
public void initialize(ConfigurableWebApplicationContext applicationContext) {
|
||||
applicationContext.getServletContext().setAttribute("otherInitialized", "true");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue