diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationExcludeFilter.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationExcludeFilter.java new file mode 100644 index 00000000000..efc4ea7fa51 --- /dev/null +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationExcludeFilter.java @@ -0,0 +1,71 @@ +/* + * 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.autoconfigure; + +import java.io.IOException; +import java.util.List; + +import org.springframework.beans.factory.BeanClassLoaderAware; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.support.SpringFactoriesLoader; +import org.springframework.core.type.classreading.MetadataReader; +import org.springframework.core.type.classreading.MetadataReaderFactory; +import org.springframework.core.type.filter.TypeFilter; + +/** + * A {@link TypeFilter} implementation that matches registered auto-configuration + * classes. + * + * @author Stephane Nicoll + * @since 1.5.0 + */ +public class AutoConfigurationExcludeFilter implements TypeFilter, BeanClassLoaderAware { + + private ClassLoader beanClassLoader; + + private List candidateAutoConfigurations; + + @Override + public void setBeanClassLoader(ClassLoader beanClassLoader) { + this.beanClassLoader = beanClassLoader; + } + + @Override + public boolean match(MetadataReader metadataReader, + MetadataReaderFactory metadataReaderFactory) throws IOException { + return isConfiguration(metadataReader) && isAutoConfiguration(metadataReader); + } + + protected List getCandidateAutoConfigurations() { + if (this.candidateAutoConfigurations == null) { + this.candidateAutoConfigurations = SpringFactoriesLoader.loadFactoryNames( + EnableAutoConfiguration.class, this.beanClassLoader); + } + return this.candidateAutoConfigurations; + } + + private boolean isConfiguration(MetadataReader metadataReader) { + return metadataReader.getAnnotationMetadata() + .isAnnotated(Configuration.class.getName()); + } + + private boolean isAutoConfiguration(MetadataReader metadataReader) { + return getCandidateAutoConfigurations().contains( + metadataReader.getClassMetadata().getClassName()); + } + +} diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/SpringBootApplication.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/SpringBootApplication.java index 20052873c6c..8967ec09354 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/SpringBootApplication.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/SpringBootApplication.java @@ -49,7 +49,9 @@ import org.springframework.core.annotation.AliasFor; @Inherited @SpringBootConfiguration @EnableAutoConfiguration -@ComponentScan(excludeFilters = @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class)) +@ComponentScan(excludeFilters = { + @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), + @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication { /** diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/AutoConfigurationExcludeFilterTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/AutoConfigurationExcludeFilterTests.java new file mode 100644 index 00000000000..411f10b0487 --- /dev/null +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/AutoConfigurationExcludeFilterTests.java @@ -0,0 +1,80 @@ +/* + * 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.autoconfigure; + +import java.util.Collections; +import java.util.List; + +import org.junit.After; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.boot.autoconfigure.context.filtersample.ExampleConfiguration; +import org.springframework.boot.autoconfigure.context.filtersample.ExampleFilteredAutoConfiguration; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link AutoConfigurationExcludeFilter}. + * + * @author Stephane Nicoll + */ +public class AutoConfigurationExcludeFilterTests { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + private AnnotationConfigApplicationContext context; + + @After + public void cleanUp() { + if (this.context != null) { + this.context.close(); + } + } + + @Test + public void filterExcludeAutoConfiguration() { + this.context = new AnnotationConfigApplicationContext(Config.class); + assertThat(this.context.getBeansOfType(String.class)).hasSize(1); + assertThat(this.context.getBean(String.class)).isEqualTo("test"); + this.thrown.expect(NoSuchBeanDefinitionException.class); + this.context.getBean(ExampleFilteredAutoConfiguration.class); + } + + + @Configuration + @ComponentScan(basePackageClasses = ExampleConfiguration.class, excludeFilters = @ComponentScan.Filter(type = FilterType.CUSTOM, classes = TestAutoConfigurationExcludeFilter.class)) + static class Config { + + } + + static class TestAutoConfigurationExcludeFilter + extends AutoConfigurationExcludeFilter { + @Override + protected List getCandidateAutoConfigurations() { + return Collections.singletonList(ExampleFilteredAutoConfiguration.class.getName()); + } + } + +} diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/context/filtersample/ExampleConfiguration.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/context/filtersample/ExampleConfiguration.java new file mode 100644 index 00000000000..af951723130 --- /dev/null +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/context/filtersample/ExampleConfiguration.java @@ -0,0 +1,30 @@ +/* + * 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.autoconfigure.context.filtersample; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ExampleConfiguration { + + @Bean + public String example() { + return "test"; + } + +} diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/context/filtersample/ExampleFilteredAutoConfiguration.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/context/filtersample/ExampleFilteredAutoConfiguration.java new file mode 100644 index 00000000000..9a4ebf50267 --- /dev/null +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/context/filtersample/ExampleFilteredAutoConfiguration.java @@ -0,0 +1,30 @@ +/* + * 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.autoconfigure.context.filtersample; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ExampleFilteredAutoConfiguration { + + @Bean + public String anotherExample() { + return "fail"; + } + +}