Introduced "globalInitializerClasses" next to the existing "contextInitializerClasses", applying to FrameworkServlets as well
Issue: SPR-11314
This commit is contained in:
@@ -20,7 +20,6 @@ import java.io.IOException;
|
||||
import java.security.Principal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@@ -40,14 +39,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;
|
||||
@@ -175,6 +177,13 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic
|
||||
/** 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;
|
||||
|
||||
@@ -199,13 +208,6 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic
|
||||
/** 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
|
||||
@@ -339,29 +341,6 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic
|
||||
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)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
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
|
||||
@@ -378,6 +357,28 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic
|
||||
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)
|
||||
*/
|
||||
public void setContextInitializers(ApplicationContextInitializer<ConfigurableApplicationContext>... contextInitializers) {
|
||||
for (ApplicationContextInitializer<ConfigurableApplicationContext> initializer : contextInitializers) {
|
||||
this.contextInitializers.add(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".
|
||||
@@ -627,19 +628,16 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -657,43 +655,6 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic
|
||||
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);
|
||||
}
|
||||
}
|
||||
AnnotationAwareOrderComparator.sort(this.contextInitializers);
|
||||
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.
|
||||
@@ -711,6 +672,60 @@ public abstract class FrameworkServlet extends HttpServletBean implements Applic
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user