Ensure only supported listeners are instantiated

Previously all EventListeners were eagerly instantiated
but that can cause problems because it happens quite early
in the lifecycle. Better to be explicit about the
supported types.
This commit is contained in:
Dave Syer 2013-11-27 15:03:58 +00:00
parent aefec4c16a
commit d1dcb015b6
4 changed files with 39 additions and 9 deletions

View File

@ -47,6 +47,7 @@ import org.springframework.core.io.ResourceLoader;
import org.springframework.format.Formatter;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.context.request.RequestContextListener;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.View;
@ -134,6 +135,12 @@ public class WebMvcAutoConfiguration {
return resolver;
}
@Bean
@ConditionalOnMissingBean(RequestContextListener.class)
public RequestContextListener requestContextListener() {
return new RequestContextListener();
}
@Bean
@ConditionalOnBean(View.class)
public BeanNameViewResolver beanNameViewResolver() {

View File

@ -276,15 +276,18 @@ public class EmbeddedWebApplicationContext extends GenericWebApplicationContext
}
}
for (Entry<String, EventListener> listenerBean : getOrderedBeansOfType(EventListener.class)) {
String name = listenerBean.getKey();
EventListener listener = listenerBean.getValue();
if (ServletListenerRegistrationBean.isSupportedType(listener)
&& !filterRegistrations.contains(listener)) {
ServletListenerRegistrationBean<EventListener> registration = new ServletListenerRegistrationBean<EventListener>(
listener);
registration.setName(name);
initializers.add(registration);
Set<Class<?>> listenerTypes = ServletListenerRegistrationBean.getSupportedTypes();
for (Class<?> type : listenerTypes) {
for (Entry<String, ?> listenerBean : getOrderedBeansOfType(type)) {
String name = listenerBean.getKey();
EventListener listener = (EventListener) listenerBean.getValue();
if (ServletListenerRegistrationBean.isSupportedType(listener)
&& !filterRegistrations.contains(listener)) {
ServletListenerRegistrationBean<EventListener> registration = new ServletListenerRegistrationBean<EventListener>(
listener);
registration.setName(name);
initializers.add(registration);
}
}
}

View File

@ -118,4 +118,11 @@ public class ServletListenerRegistrationBean<T extends EventListener> extends
return false;
}
/**
* @return the supportedTypes for this registration
*/
public static Set<Class<?>> getSupportedTypes() {
return SUPPORTED_TYPES;
}
}

View File

@ -22,6 +22,7 @@ import java.util.Properties;
import javax.servlet.Filter;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextListener;
import org.junit.After;
import org.junit.Before;
@ -264,6 +265,18 @@ public class EmbeddedWebApplicationContextTests {
ordered.verify(initializer2).onStartup(servletContext);
}
@Test
public void servletContextListenerBeans() throws Exception {
addEmbeddedServletContainerFactoryBean();
ServletContextListener initializer = mock(ServletContextListener.class);
this.context.registerBeanDefinition("initializerBean",
beanDefinition(initializer));
this.context.refresh();
ServletContext servletContext = getEmbeddedServletContainerFactory()
.getServletContext();
verify(servletContext).addListener(initializer);
}
@Test
public void unorderedServletContextInitializerBeans() throws Exception {
addEmbeddedServletContainerFactoryBean();