Defer WebApplicationContext initialization

Update SpringBootServletInitializer so that the WebApplicationContext is
not initialized until ServletContextListener.contextInitialized() is
called. This makes it easier to subclass SpringBootServletInitializer
to add additional listeners to be called in a specific order.

Fixes gh-2070
This commit is contained in:
Phillip Webb
2014-12-08 18:18:27 -08:00
parent d33c0ebf8f
commit 17631486f2

View File

@@ -20,6 +20,7 @@ import javax.servlet.Filter;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletException;
import org.apache.commons.logging.Log;
@@ -62,20 +63,7 @@ public abstract class SpringBootServletInitializer implements WebApplicationInit
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
WebApplicationContext rootAppContext = createRootApplicationContext(servletContext);
if (rootAppContext != null) {
servletContext.addListener(new ContextLoaderListener(rootAppContext) {
@Override
public void contextInitialized(ServletContextEvent event) {
// no-op because the application context is already initialized
}
});
}
else {
this.logger.debug("No ContextLoaderListener registered, as "
+ "createRootApplicationContext() did not "
+ "return an application context");
}
servletContext.addListener(new Listener());
}
protected WebApplicationContext createRootApplicationContext(
@@ -136,4 +124,36 @@ public abstract class SpringBootServletInitializer implements WebApplicationInit
return application;
}
/**
* {@link ServletContextListener} used to load the context
*/
private class Listener implements ServletContextListener {
private ContextLoaderListener contextLoaderListener;
@Override
public void contextInitialized(ServletContextEvent event) {
ServletContext servletContext = event.getServletContext();
WebApplicationContext applicationContext = createRootApplicationContext(servletContext);
if (applicationContext == null) {
SpringBootServletInitializer.this.logger
.debug("No ContextLoaderListener registered, as "
+ "createRootApplicationContext() did not "
+ "return an application context");
}
else {
this.contextLoaderListener = new ContextLoaderListener(applicationContext);
// Don't delegate contextInitialized event as we're already setup
}
}
@Override
public void contextDestroyed(ServletContextEvent event) {
if (this.contextLoaderListener != null) {
this.contextLoaderListener.contextDestroyed(event);
}
}
}
}