From 4919c6f30ce1f6842f40c24e8cb697d7a075f0e5 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 1 Nov 2016 10:24:33 +0000 Subject: [PATCH] Ignore scoped targets when collecting servlet context initializer beans Previously, there were two problems with servlet context initializer beans that are a scoped proxy: 1. When there's no explicit registration bean the target of the scoped proxy is registered rather than the proxy. This meant that the proxy had no effect as it was being bypassed. 2. When there is an explicit registration bean, the registration is performed twice: the faulty implicit registration described above and explicit registration. A fix (SPR-14816) has been made in Spring Framework so that we can correctly determine the type of bean that will be produced by a scoped proxy's factory bean. That change, coupled with the change in this commit that ignored beans that are the target of a scoped proxy addresses both of the problems described above. A single registration is now performed and its the scoped proxy, rather than its target, that is registered. Closes gh-7150 --- .../ServletContextInitializerBeans.java | 3 +- .../FilterRegistrationIntegrationTests.java | 95 +++++++++++++++++++ 2 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 spring-boot/src/test/java/org/springframework/boot/web/servlet/FilterRegistrationIntegrationTests.java diff --git a/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java b/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java index ffafe68630..9fa88ff166 100644 --- a/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java +++ b/spring-boot/src/main/java/org/springframework/boot/web/servlet/ServletContextInitializerBeans.java @@ -36,6 +36,7 @@ import javax.servlet.Servlet; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.aop.scope.ScopedProxyUtils; import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.core.annotation.AnnotationAwareOrderComparator; @@ -229,7 +230,7 @@ public class ServletContextInitializerBeans String[] names = beanFactory.getBeanNamesForType(type, true, false); Map map = new LinkedHashMap(); for (String name : names) { - if (!excludes.contains(name)) { + if (!excludes.contains(name) && !ScopedProxyUtils.isScopedTarget(name)) { T bean = beanFactory.getBean(name, type); if (!excludes.contains(bean)) { map.put(name, bean); diff --git a/spring-boot/src/test/java/org/springframework/boot/web/servlet/FilterRegistrationIntegrationTests.java b/spring-boot/src/test/java/org/springframework/boot/web/servlet/FilterRegistrationIntegrationTests.java new file mode 100644 index 0000000000..6241afc0a1 --- /dev/null +++ b/spring-boot/src/test/java/org/springframework/boot/web/servlet/FilterRegistrationIntegrationTests.java @@ -0,0 +1,95 @@ +/* + * Copyright 2012-2016 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.web.servlet; + +import javax.servlet.Filter; + +import org.junit.After; +import org.junit.Test; + +import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext; +import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; +import org.springframework.boot.testutil.MockFilter; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Integration tests for {@link Filter} registration. + * + * @author Andy Wilkinson + */ +public class FilterRegistrationIntegrationTests { + + private AnnotationConfigEmbeddedWebApplicationContext context; + + @After + public void cleanUp() { + if (this.context != null) { + this.context.close(); + } + } + + @Test + public void normalFiltersAreRegistered() { + load(FilterConfiguration.class); + assertThat(this.context.getServletContext().getFilterRegistrations()).hasSize(1); + } + + @Test + public void scopedTargetFiltersAreNotRegistered() { + load(ScopedTargetFilterConfiguration.class); + assertThat(this.context.getServletContext().getFilterRegistrations()).isEmpty(); + } + + private void load(Class configuration) { + this.context = new AnnotationConfigEmbeddedWebApplicationContext( + ContainerConfiguration.class, configuration); + } + + @Configuration + static class ContainerConfiguration { + + @Bean + public TomcatEmbeddedServletContainerFactory servletContainerFactory() { + return new TomcatEmbeddedServletContainerFactory(0); + } + + } + + @Configuration + static class ScopedTargetFilterConfiguration { + + @Bean(name = "scopedTarget.myFilter") + public Filter myFilter() { + return new MockFilter(); + } + + } + + @Configuration + static class FilterConfiguration { + + @Bean + public Filter myFilter() { + return new MockFilter(); + } + + } + +}