diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/EnableAutoConfigurationImportSelector.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/EnableAutoConfigurationImportSelector.java index df815ef486d..af199cc05fb 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/EnableAutoConfigurationImportSelector.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/EnableAutoConfigurationImportSelector.java @@ -85,6 +85,7 @@ public class EnableAutoConfigurationImportSelector attributes); configurations = removeDuplicates(configurations); Set exclusions = getExclusions(metadata, attributes); + checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); configurations = sort(configurations); recordWithConditionEvaluationReport(configurations, exclusions); @@ -157,6 +158,23 @@ public class EnableAutoConfigurationImportSelector return EnableAutoConfiguration.class; } + private void checkExcludedClasses(List configurations, + Set exclusions) { + StringBuilder message = new StringBuilder(); + for (String exclusion : exclusions) { + if (ClassUtils.isPresent(exclusion, getClass().getClassLoader()) + && !configurations.contains(exclusion)) { + message.append("\t- ").append(exclusion).append("\n"); + } + } + if (!message.toString().isEmpty()) { + throw new IllegalStateException( + "The following classes could not be excluded because they are not auto-configuration classes:\n" + + message.toString()); + } + + } + /** * Return any exclusions that limit the candidate configurations. * @param metadata the source metadata diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/EnableAutoConfigurationImportSelectorTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/EnableAutoConfigurationImportSelectorTests.java index 306b132ac9c..91154a68ba0 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/EnableAutoConfigurationImportSelectorTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/EnableAutoConfigurationImportSelectorTests.java @@ -19,7 +19,9 @@ package org.springframework.boot.autoconfigure; import java.util.List; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -29,6 +31,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionEvaluationRepor import org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration; import org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration; import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration; +import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.support.SpringFactoriesLoader; @@ -60,6 +63,9 @@ public class EnableAutoConfigurationImportSelectorTests { @Mock private AnnotationAttributes annotationAttributes; + @Rule + public ExpectedException expected = ExpectedException.none(); + @Before public void setup() { MockitoAnnotations.initMocks(this); @@ -166,6 +172,47 @@ public class EnableAutoConfigurationImportSelectorTests { assertThat(imports).isEmpty(); } + @Test + public void nonAutoConfigurationClassExclusionsShouldThrowException() throws Exception { + this.expected.expect(IllegalStateException.class); + configureExclusions(new String[] { TestConfiguration.class.getName() }, + new String[0], new String[0]); + this.importSelector.selectImports(this.annotationMetadata); + } + + @Test + public void nonAutoConfigurationClassNameExclusionsWhenPresentOnClassPathShouldThrowException() + throws Exception { + this.expected.expect(IllegalStateException.class); + configureExclusions(new String[0], + new String[] { "org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelectorTests.TestConfiguration" }, + new String[0]); + this.importSelector.selectImports(this.annotationMetadata); + } + + @Test + public void nonAutoConfigurationPropertyExclusionsWhenPresentOnClassPathShouldThrowException() + throws Exception { + this.expected.expect(IllegalStateException.class); + configureExclusions(new String[0], + new String[0], + new String[] { "org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelectorTests.TestConfiguration" }); + this.importSelector.selectImports(this.annotationMetadata); + } + + @Test + public void nameAndPropertyExclusionsWhenNotPresentOnClasspathShouldNotThrowException() + throws Exception { + configureExclusions(new String[0], + new String[] { "org.springframework.boot.autoconfigure.DoesNotExist1" }, + new String[] { "org.springframework.boot.autoconfigure.DoesNotExist2" }); + this.importSelector.selectImports(this.annotationMetadata); + assertThat(ConditionEvaluationReport.get(this.beanFactory).getExclusions()) + .contains("org.springframework.boot.autoconfigure.DoesNotExist1"); + assertThat(ConditionEvaluationReport.get(this.beanFactory).getExclusions()) + .contains("org.springframework.boot.autoconfigure.DoesNotExist2"); + } + private void configureExclusions(String[] classExclusion, String[] nameExclusion, String[] propertyExclusion) { String annotationName = EnableAutoConfiguration.class.getName(); @@ -187,4 +234,9 @@ public class EnableAutoConfigurationImportSelectorTests { getClass().getClassLoader()); } + @Configuration + private class TestConfiguration { + + } + }