Introduce ContextLoader(Listener) constructors
Constructors have been added to both ContextLoader and ContextLoaderListener to support instance-based programmatic registration of listeners within ServletContainerInitializer implementations in Servlet 3.0+ environments, and more particularly when using Spring 3.1's WebApplicationInitializer SPI. Issue: SPR-7672
This commit is contained in:
parent
2b4328023e
commit
e36b5e9b7e
|
|
@ -37,7 +37,6 @@ import org.springframework.context.ApplicationContextInitializer;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.context.access.ContextSingletonBeanFactoryLocator;
|
import org.springframework.context.access.ContextSingletonBeanFactoryLocator;
|
||||||
import org.springframework.core.GenericTypeResolver;
|
import org.springframework.core.GenericTypeResolver;
|
||||||
import org.springframework.core.Ordered;
|
|
||||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
import org.springframework.core.io.support.PropertiesLoaderUtils;
|
import org.springframework.core.io.support.PropertiesLoaderUtils;
|
||||||
|
|
@ -76,6 +75,11 @@ import org.springframework.util.StringUtils;
|
||||||
* the root application context. See the
|
* the root application context. See the
|
||||||
* {@link #loadParentContext(ServletContext)} method for more information.
|
* {@link #loadParentContext(ServletContext)} method for more information.
|
||||||
*
|
*
|
||||||
|
* <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.
|
||||||
|
*
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @author Colin Sampaleanu
|
* @author Colin Sampaleanu
|
||||||
* @author Sam Brannen
|
* @author Sam Brannen
|
||||||
|
|
@ -184,12 +188,69 @@ public class ContextLoader {
|
||||||
private BeanFactoryReference parentContextRef;
|
private BeanFactoryReference parentContextRef;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@code ContextLoader} that will create a web application context
|
||||||
|
* based on the "contextClass" and "contextConfigLocation" servlet context-params.
|
||||||
|
* See class-level documentation for details on default values for each.
|
||||||
|
* <p>This constructor is typically used when declaring the {@code
|
||||||
|
* ContextLoaderListener} subclass as a {@code <listener>} within {@code web.xml}, as
|
||||||
|
* a no-arg constructor is required.
|
||||||
|
* <p>The created application context will be registered into the ServletContext under
|
||||||
|
* the attribute name {@link WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE}
|
||||||
|
* and subclasses are free to call the {@link #closeWebApplicationContext} method on
|
||||||
|
* container shutdown to close the application context.
|
||||||
|
* @see #ContextLoader(WebApplicationContext)
|
||||||
|
* @see #initWebApplicationContext(ServletContext)
|
||||||
|
* @see #closeWebApplicationContext(ServletContext)
|
||||||
|
*/
|
||||||
|
public ContextLoader() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@code ContextLoader} with the given application context. This
|
||||||
|
* constructor is useful in Servlet 3.0+ environments where instance-based
|
||||||
|
* registration of listeners is possible through the {@link ServletContext#addListener}
|
||||||
|
* API.
|
||||||
|
* <p>The context may or may not yet be {@linkplain
|
||||||
|
* ConfigurableApplicationContext#refresh() refreshed}. If it (a) is an implementation
|
||||||
|
* of {@link ConfigurableWebApplicationContext} and (b) has <strong>not</strong>
|
||||||
|
* already been refreshed (the recommended approach), then the following will occur:
|
||||||
|
* <ul>
|
||||||
|
* <li>If the given context has not already been assigned an {@linkplain
|
||||||
|
* ConfigurableApplicationContext#setId id}, one will be assigned to it</li>
|
||||||
|
* <li>{@code ServletContext} and {@code ServletConfig} objects will be delegated to
|
||||||
|
* the application context</li>
|
||||||
|
* <li>{@link #customizeContext} will be called</li>
|
||||||
|
* <li>Any {@link ApplicationContextInitializer}s specified through the
|
||||||
|
* "contextInitializerClasses" init-param will be applied.</li>
|
||||||
|
* <li>{@link ConfigurableApplicationContext#refresh refresh()} will be called</li>
|
||||||
|
* </ul>
|
||||||
|
* If the context has already been refreshed or does not implement
|
||||||
|
* {@code ConfigurableWebApplicationContext}, none of the above will occur under the
|
||||||
|
* assumption that the user has performed these actions (or not) per his or her
|
||||||
|
* specific needs.
|
||||||
|
* <p>See {@link org.springframework.web.WebApplicationInitializer} for usage examples.
|
||||||
|
* <p>In any case, the given application context will be registered into the
|
||||||
|
* ServletContext under the attribute name {@link
|
||||||
|
* WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE} and subclasses are
|
||||||
|
* free to call the {@link #closeWebApplicationContext} method on container shutdown
|
||||||
|
* to close the application context.
|
||||||
|
* @param context the application context to manage
|
||||||
|
* @see #initWebApplicationContext(ServletContext)
|
||||||
|
* @see #closeWebApplicationContext(ServletContext)
|
||||||
|
*/
|
||||||
|
public ContextLoader(WebApplicationContext context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize Spring's web application context for the given servlet context,
|
* Initialize Spring's web application context for the given servlet context,
|
||||||
|
* using the application context provided at construction time, or creating a new one
|
||||||
* according to the "{@link #CONTEXT_CLASS_PARAM contextClass}" and
|
* according to the "{@link #CONTEXT_CLASS_PARAM contextClass}" and
|
||||||
* "{@link #CONFIG_LOCATION_PARAM contextConfigLocation}" context-params.
|
* "{@link #CONFIG_LOCATION_PARAM contextConfigLocation}" context-params.
|
||||||
* @param servletContext current servlet context
|
* @param servletContext current servlet context
|
||||||
* @return the new WebApplicationContext
|
* @return the new WebApplicationContext
|
||||||
|
* @see #ContextLoader(WebApplicationContext)
|
||||||
* @see #CONTEXT_CLASS_PARAM
|
* @see #CONTEXT_CLASS_PARAM
|
||||||
* @see #CONFIG_LOCATION_PARAM
|
* @see #CONFIG_LOCATION_PARAM
|
||||||
*/
|
*/
|
||||||
|
|
@ -208,12 +269,14 @@ public class ContextLoader {
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Determine parent for root web application context, if any.
|
|
||||||
ApplicationContext parent = loadParentContext(servletContext);
|
|
||||||
|
|
||||||
// Store context in local instance variable, to guarantee that
|
// Store context in local instance variable, to guarantee that
|
||||||
// it is available on ServletContext shutdown.
|
// it is available on ServletContext shutdown.
|
||||||
this.context = createWebApplicationContext(servletContext, parent);
|
if (this.context == null) {
|
||||||
|
this.context = createWebApplicationContext(servletContext);
|
||||||
|
}
|
||||||
|
if (this.context instanceof ConfigurableWebApplicationContext) {
|
||||||
|
configureAndRefreshWebApplicationContext((ConfigurableWebApplicationContext)this.context, servletContext);
|
||||||
|
}
|
||||||
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
|
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
|
||||||
|
|
||||||
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
|
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
|
||||||
|
|
@ -260,7 +323,7 @@ public class ContextLoader {
|
||||||
* @return the root WebApplicationContext
|
* @return the root WebApplicationContext
|
||||||
* @see ConfigurableWebApplicationContext
|
* @see ConfigurableWebApplicationContext
|
||||||
*/
|
*/
|
||||||
protected WebApplicationContext createWebApplicationContext(ServletContext sc, ApplicationContext parent) {
|
protected WebApplicationContext createWebApplicationContext(ServletContext sc) {
|
||||||
Class<?> contextClass = determineContextClass(sc);
|
Class<?> contextClass = determineContextClass(sc);
|
||||||
if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
|
if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
|
||||||
throw new ApplicationContextException("Custom context class [" + contextClass.getName() +
|
throw new ApplicationContextException("Custom context class [" + contextClass.getName() +
|
||||||
|
|
@ -268,32 +331,50 @@ public class ContextLoader {
|
||||||
}
|
}
|
||||||
ConfigurableWebApplicationContext wac =
|
ConfigurableWebApplicationContext wac =
|
||||||
(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
|
(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
|
||||||
|
return wac;
|
||||||
|
}
|
||||||
|
|
||||||
// Assign the best possible id value.
|
/**
|
||||||
if (sc.getMajorVersion() == 2 && sc.getMinorVersion() < 5) {
|
* @deprecated as of Spring 3.1 in favor of
|
||||||
// Servlet <= 2.4: resort to name specified in web.xml, if any.
|
* {@link #createWebApplicationContext(ServletContext)} and
|
||||||
String servletContextName = sc.getServletContextName();
|
* {@link #configureAndRefreshWebApplicationContext(WebApplicationContext, ServletContext)}
|
||||||
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
|
*/
|
||||||
ObjectUtils.getDisplayString(servletContextName));
|
@Deprecated
|
||||||
}
|
protected WebApplicationContext createWebApplicationContext(ServletContext sc, ApplicationContext parent) {
|
||||||
else {
|
return createWebApplicationContext(sc);
|
||||||
// Servlet 2.5's getContextPath available!
|
}
|
||||||
try {
|
|
||||||
String contextPath = (String) ServletContext.class.getMethod("getContextPath").invoke(sc);
|
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
|
||||||
|
if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
|
||||||
|
// The application context id is still set to its original default value
|
||||||
|
// -> assign a more useful id based on available information
|
||||||
|
if (sc.getMajorVersion() == 2 && sc.getMinorVersion() < 5) {
|
||||||
|
// Servlet <= 2.4: resort to name specified in web.xml, if any.
|
||||||
|
String servletContextName = sc.getServletContextName();
|
||||||
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
|
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
|
||||||
ObjectUtils.getDisplayString(contextPath));
|
ObjectUtils.getDisplayString(servletContextName));
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
else {
|
||||||
throw new IllegalStateException("Failed to invoke Servlet 2.5 getContextPath method", ex);
|
// Servlet 2.5's getContextPath available!
|
||||||
|
try {
|
||||||
|
String contextPath = (String) ServletContext.class.getMethod("getContextPath").invoke(sc);
|
||||||
|
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
|
||||||
|
ObjectUtils.getDisplayString(contextPath));
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
throw new IllegalStateException("Failed to invoke Servlet 2.5 getContextPath method", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Determine parent for root web application context, if any.
|
||||||
|
ApplicationContext parent = loadParentContext(sc);
|
||||||
|
|
||||||
wac.setParent(parent);
|
wac.setParent(parent);
|
||||||
wac.setServletContext(sc);
|
wac.setServletContext(sc);
|
||||||
wac.setConfigLocation(sc.getInitParameter(CONFIG_LOCATION_PARAM));
|
wac.setConfigLocation(sc.getInitParameter(CONFIG_LOCATION_PARAM));
|
||||||
customizeContext(sc, wac);
|
customizeContext(sc, wac);
|
||||||
wac.refresh();
|
wac.refresh();
|
||||||
return wac;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2009 the original author or authors.
|
* Copyright 2002-2011 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -27,8 +27,15 @@ import javax.servlet.ServletContextListener;
|
||||||
* {@link org.springframework.web.util.Log4jConfigListener}
|
* {@link org.springframework.web.util.Log4jConfigListener}
|
||||||
* in <code>web.xml</code>, if the latter is used.
|
* in <code>web.xml</code>, if the latter is used.
|
||||||
*
|
*
|
||||||
|
* <p>As of Spring 3.1, {@code ContextLoaderListener} supports injecting the root web
|
||||||
|
* application context via the {@link #ContextLoaderListener(WebApplicationContext)}
|
||||||
|
* constructor, allowing for programmatic configuration in Servlet 3.0+ environments. See
|
||||||
|
* {@link org.springframework.web.WebApplicationInitializer} for usage examples.
|
||||||
|
*
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
|
* @author Chris Beams
|
||||||
* @since 17.02.2003
|
* @since 17.02.2003
|
||||||
|
* @see org.springframework.web.WebApplicationInitializer
|
||||||
* @see org.springframework.web.util.Log4jConfigListener
|
* @see org.springframework.web.util.Log4jConfigListener
|
||||||
*/
|
*/
|
||||||
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
|
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
|
||||||
|
|
@ -36,6 +43,63 @@ public class ContextLoaderListener extends ContextLoader implements ServletConte
|
||||||
private ContextLoader contextLoader;
|
private ContextLoader contextLoader;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@code ContextLoaderListener} that will create a web application
|
||||||
|
* context based on the "contextClass" and "contextConfigLocation" servlet
|
||||||
|
* context-params. See {@link ContextLoader} superclass documentation for details on
|
||||||
|
* default values for each.
|
||||||
|
* <p>This constructor is typically used when declaring {@code ContextLoaderListener}
|
||||||
|
* as a {@code <listener>} within {@code web.xml}, where a no-arg constructor is
|
||||||
|
* required.
|
||||||
|
* <p>The created application context will be registered into the ServletContext under
|
||||||
|
* the attribute name {@link WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE}
|
||||||
|
* and the Spring application context will be closed when the {@link #contextDestroyed}
|
||||||
|
* lifecycle method is invoked on this listener.
|
||||||
|
* @see ContextLoader
|
||||||
|
* @see #ContextLoaderListener(WebApplicationContext)
|
||||||
|
* @see #contextInitialized(ServletContextEvent)
|
||||||
|
* @see #contextDestroyed(ServletContextEvent)
|
||||||
|
*/
|
||||||
|
public ContextLoaderListener() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@code ContextLoaderListener} with the given application context. This
|
||||||
|
* constructor is useful in Servlet 3.0+ environments where instance-based
|
||||||
|
* registration of listeners is possible through the {@link ServletContext#addListener}
|
||||||
|
* API.
|
||||||
|
* <p>The context may or may not yet be {@linkplain
|
||||||
|
* ConfigurableApplicationContext#refresh() refreshed}. If it (a) is an implementation
|
||||||
|
* of {@link ConfigurableWebApplicationContext} and (b) has <strong>not</strong>
|
||||||
|
* already been refreshed (the recommended approach), then the following will occur:
|
||||||
|
* <ul>
|
||||||
|
* <li>If the given context has not already been assigned an {@linkplain
|
||||||
|
* ConfigurableApplicationContext#setId id}, one will be assigned to it</li>
|
||||||
|
* <li>{@code ServletContext} and {@code ServletConfig} objects will be delegated to
|
||||||
|
* the application context</li>
|
||||||
|
* <li>{@link #customizeContext} will be called</li>
|
||||||
|
* <li>Any {@link ApplicationContextInitializer}s specified through the
|
||||||
|
* "contextInitializerClasses" init-param will be applied.</li>
|
||||||
|
* <li>{@link ConfigurableApplicationContext#refresh refresh()} will be called</li>
|
||||||
|
* </ul>
|
||||||
|
* If the context has already been refreshed or does not implement
|
||||||
|
* {@code ConfigurableWebApplicationContext}, none of the above will occur under the
|
||||||
|
* assumption that the user has performed these actions (or not) per his or her
|
||||||
|
* specific needs.
|
||||||
|
* <p>See {@link org.springframework.web.WebApplicationInitializer} for usage examples.
|
||||||
|
* <p>In any case, the given application context will be registered into the
|
||||||
|
* ServletContext under the attribute name {@link
|
||||||
|
* WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE} and the Spring
|
||||||
|
* application context will be closed when the {@link #contextDestroyed} lifecycle
|
||||||
|
* method is invoked on this listener.
|
||||||
|
* @param context the application context to manage
|
||||||
|
* @see #contextInitialized(ServletContextEvent)
|
||||||
|
* @see #contextDestroyed(ServletContextEvent)
|
||||||
|
*/
|
||||||
|
public ContextLoaderListener(WebApplicationContext context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the root web application context.
|
* Initialize the root web application context.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue