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.access.ContextSingletonBeanFactoryLocator;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.support.PropertiesLoaderUtils;
|
||||
|
|
@ -76,6 +75,11 @@ import org.springframework.util.StringUtils;
|
|||
* the root application context. See the
|
||||
* {@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 Colin Sampaleanu
|
||||
* @author Sam Brannen
|
||||
|
|
@ -184,12 +188,69 @@ public class ContextLoader {
|
|||
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,
|
||||
* using the application context provided at construction time, or creating a new one
|
||||
* according to the "{@link #CONTEXT_CLASS_PARAM contextClass}" and
|
||||
* "{@link #CONFIG_LOCATION_PARAM contextConfigLocation}" context-params.
|
||||
* @param servletContext current servlet context
|
||||
* @return the new WebApplicationContext
|
||||
* @see #ContextLoader(WebApplicationContext)
|
||||
* @see #CONTEXT_CLASS_PARAM
|
||||
* @see #CONFIG_LOCATION_PARAM
|
||||
*/
|
||||
|
|
@ -208,12 +269,14 @@ public class ContextLoader {
|
|||
long startTime = System.currentTimeMillis();
|
||||
|
||||
try {
|
||||
// Determine parent for root web application context, if any.
|
||||
ApplicationContext parent = loadParentContext(servletContext);
|
||||
|
||||
// Store context in local instance variable, to guarantee that
|
||||
// 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);
|
||||
|
||||
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
|
||||
|
|
@ -260,7 +323,7 @@ public class ContextLoader {
|
|||
* @return the root WebApplicationContext
|
||||
* @see ConfigurableWebApplicationContext
|
||||
*/
|
||||
protected WebApplicationContext createWebApplicationContext(ServletContext sc, ApplicationContext parent) {
|
||||
protected WebApplicationContext createWebApplicationContext(ServletContext sc) {
|
||||
Class<?> contextClass = determineContextClass(sc);
|
||||
if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
|
||||
throw new ApplicationContextException("Custom context class [" + contextClass.getName() +
|
||||
|
|
@ -268,32 +331,50 @@ public class ContextLoader {
|
|||
}
|
||||
ConfigurableWebApplicationContext wac =
|
||||
(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
|
||||
return wac;
|
||||
}
|
||||
|
||||
// Assign the best possible id value.
|
||||
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 +
|
||||
ObjectUtils.getDisplayString(servletContextName));
|
||||
}
|
||||
else {
|
||||
// Servlet 2.5's getContextPath available!
|
||||
try {
|
||||
String contextPath = (String) ServletContext.class.getMethod("getContextPath").invoke(sc);
|
||||
/**
|
||||
* @deprecated as of Spring 3.1 in favor of
|
||||
* {@link #createWebApplicationContext(ServletContext)} and
|
||||
* {@link #configureAndRefreshWebApplicationContext(WebApplicationContext, ServletContext)}
|
||||
*/
|
||||
@Deprecated
|
||||
protected WebApplicationContext createWebApplicationContext(ServletContext sc, ApplicationContext parent) {
|
||||
return createWebApplicationContext(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 +
|
||||
ObjectUtils.getDisplayString(contextPath));
|
||||
ObjectUtils.getDisplayString(servletContextName));
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException("Failed to invoke Servlet 2.5 getContextPath method", ex);
|
||||
else {
|
||||
// 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.setServletContext(sc);
|
||||
wac.setConfigLocation(sc.getInitParameter(CONFIG_LOCATION_PARAM));
|
||||
customizeContext(sc, wac);
|
||||
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");
|
||||
* 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}
|
||||
* 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 Chris Beams
|
||||
* @since 17.02.2003
|
||||
* @see org.springframework.web.WebApplicationInitializer
|
||||
* @see org.springframework.web.util.Log4jConfigListener
|
||||
*/
|
||||
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
|
||||
|
|
@ -36,6 +43,63 @@ public class ContextLoaderListener extends ContextLoader implements ServletConte
|
|||
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.
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue