diff --git a/org.springframework.web/src/main/java/org/springframework/web/context/ContextLoader.java b/org.springframework.web/src/main/java/org/springframework/web/context/ContextLoader.java index 731e4b20478..5b5669f8c1d 100644 --- a/org.springframework.web/src/main/java/org/springframework/web/context/ContextLoader.java +++ b/org.springframework.web/src/main/java/org/springframework/web/context/ContextLoader.java @@ -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. * + *
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. + *
This constructor is typically used when declaring the {@code
+ * ContextLoaderListener} subclass as a {@code 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.
+ * The context may or may not yet be {@linkplain
+ * ConfigurableApplicationContext#refresh() refreshed}. If it (a) is an implementation
+ * of {@link ConfigurableWebApplicationContext} and (b) has not
+ * already been refreshed (the recommended approach), then the following will occur:
+ * See {@link org.springframework.web.WebApplicationInitializer} for usage examples.
+ * 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;
}
/**
diff --git a/org.springframework.web/src/main/java/org/springframework/web/context/ContextLoaderListener.java b/org.springframework.web/src/main/java/org/springframework/web/context/ContextLoaderListener.java
index b0140f08a85..28de0fa40ec 100644
--- a/org.springframework.web/src/main/java/org/springframework/web/context/ContextLoaderListener.java
+++ b/org.springframework.web/src/main/java/org/springframework/web/context/ContextLoaderListener.java
@@ -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 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.
+ * This constructor is typically used when declaring {@code ContextLoaderListener}
+ * as a {@code 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.
+ * The context may or may not yet be {@linkplain
+ * ConfigurableApplicationContext#refresh() refreshed}. If it (a) is an implementation
+ * of {@link ConfigurableWebApplicationContext} and (b) has not
+ * already been refreshed (the recommended approach), then the following will occur:
+ * See {@link org.springframework.web.WebApplicationInitializer} for usage examples.
+ * 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.
*/
+ *
+ * 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.
+ * web.xml, if the latter is used.
*
+ *
+ *
+ * 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.
+ *