From f93d4a0cbf3c361b31afe1c0d96b6419420e5296 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 19 Jan 2017 12:21:27 +0000 Subject: [PATCH] Add explicit aliases for exclude and excludeName on SpringBootApplication Previously, SpringBootApplication relied on implicity aliasing of exclude and excludeName that worked because the two attributes have the same names as the equivalent attributes on EnableAutoConfiguration. This commit updates SpringBootApplication to make the aliases explicit and also adds tests to EnableAutoConfigurationImportSelectorTests to verify that the aliasing is working as intended. Closes gh-7951 --- .../autoconfigure/SpringBootApplication.java | 4 +- ...eAutoConfigurationImportSelectorTests.java | 168 ++++++++++-------- 2 files changed, 100 insertions(+), 72 deletions(-) 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 8967ec09354..1001bfc5380 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 @@ -1,5 +1,5 @@ /* - * Copyright 2012-2016 the original author or authors. + * Copyright 2012-2017 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. @@ -58,6 +58,7 @@ public @interface SpringBootApplication { * Exclude specific auto-configuration classes such that they will never be applied. * @return the classes to exclude */ + @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "exclude") Class[] exclude() default {}; /** @@ -66,6 +67,7 @@ public @interface SpringBootApplication { * @return the class names to exclude * @since 1.3.0 */ + @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "excludeName") String[] excludeName() default {}; /** 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 bec67e8f0f9..7c95df0df5d 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 @@ -22,7 +22,6 @@ 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; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; @@ -32,15 +31,12 @@ import org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfigura 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; -import org.springframework.core.type.AnnotationMetadata; +import org.springframework.core.type.StandardAnnotationMetadata; import org.springframework.mock.env.MockEnvironment; -import org.springframework.util.StringUtils; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.BDDMockito.given; /** * Tests for {@link EnableAutoConfigurationImportSelector} @@ -57,12 +53,6 @@ public class EnableAutoConfigurationImportSelectorTests { private final MockEnvironment environment = new MockEnvironment(); - @Mock - private AnnotationMetadata annotationMetadata; - - @Mock - private AnnotationAttributes annotationAttributes; - @Rule public ExpectedException expected = ExpectedException.none(); @@ -75,9 +65,8 @@ public class EnableAutoConfigurationImportSelectorTests { } @Test - public void importsAreSelected() { - configureExclusions(new String[0], new String[0], new String[0]); - String[] imports = this.importSelector.selectImports(this.annotationMetadata); + public void importsAreSelectedWhenUsingEnableAutoConfiguration() { + String[] imports = selectImports(BasicEnableAutoConfiguration.class); assertThat(imports).hasSameSizeAs(SpringFactoriesLoader.loadFactoryNames( EnableAutoConfiguration.class, getClass().getClassLoader())); assertThat(ConditionEvaluationReport.get(this.beanFactory).getExclusions()) @@ -86,9 +75,16 @@ public class EnableAutoConfigurationImportSelectorTests { @Test public void classExclusionsAreApplied() { - configureExclusions(new String[] { FreeMarkerAutoConfiguration.class.getName() }, - new String[0], new String[0]); - String[] imports = this.importSelector.selectImports(this.annotationMetadata); + String[] imports = selectImports( + EnableAutoConfigurationWithClassExclusions.class); + assertThat(imports).hasSize(getAutoConfigurationClassNames().size() - 1); + assertThat(ConditionEvaluationReport.get(this.beanFactory).getExclusions()) + .contains(FreeMarkerAutoConfiguration.class.getName()); + } + + @Test + public void classExclusionsAreAppliedWhenUsingSpringBootApplication() { + String[] imports = selectImports(SpringBootApplicationWithClassExclusions.class); assertThat(imports).hasSize(getAutoConfigurationClassNames().size() - 1); assertThat(ConditionEvaluationReport.get(this.beanFactory).getExclusions()) .contains(FreeMarkerAutoConfiguration.class.getName()); @@ -96,10 +92,17 @@ public class EnableAutoConfigurationImportSelectorTests { @Test public void classNamesExclusionsAreApplied() { - configureExclusions(new String[0], - new String[] { MustacheAutoConfiguration.class.getName() }, - new String[0]); - String[] imports = this.importSelector.selectImports(this.annotationMetadata); + String[] imports = selectImports( + EnableAutoConfigurationWithClassNameExclusions.class); + assertThat(imports).hasSize(getAutoConfigurationClassNames().size() - 1); + assertThat(ConditionEvaluationReport.get(this.beanFactory).getExclusions()) + .contains(MustacheAutoConfiguration.class.getName()); + } + + @Test + public void classNamesExclusionsAreAppliedWhenUsingSpringBootApplication() { + String[] imports = selectImports( + SpringBootApplicationWithClassNameExclusions.class); assertThat(imports).hasSize(getAutoConfigurationClassNames().size() - 1); assertThat(ConditionEvaluationReport.get(this.beanFactory).getExclusions()) .contains(MustacheAutoConfiguration.class.getName()); @@ -107,9 +110,9 @@ public class EnableAutoConfigurationImportSelectorTests { @Test public void propertyExclusionsAreApplied() { - configureExclusions(new String[0], new String[0], - new String[] { FreeMarkerAutoConfiguration.class.getName() }); - String[] imports = this.importSelector.selectImports(this.annotationMetadata); + this.environment.setProperty("spring.autoconfigure.exclude", + FreeMarkerAutoConfiguration.class.getName()); + String[] imports = selectImports(BasicEnableAutoConfiguration.class); assertThat(imports).hasSize(getAutoConfigurationClassNames().size() - 1); assertThat(ConditionEvaluationReport.get(this.beanFactory).getExclusions()) .contains(FreeMarkerAutoConfiguration.class.getName()); @@ -117,10 +120,10 @@ public class EnableAutoConfigurationImportSelectorTests { @Test public void severalPropertyExclusionsAreApplied() { - configureExclusions(new String[0], new String[0], - new String[] { FreeMarkerAutoConfiguration.class.getName(), - MustacheAutoConfiguration.class.getName() }); - String[] imports = this.importSelector.selectImports(this.annotationMetadata); + this.environment.setProperty("spring.autoconfigure.exclude", + FreeMarkerAutoConfiguration.class.getName() + "," + + MustacheAutoConfiguration.class.getName()); + String[] imports = selectImports(BasicEnableAutoConfiguration.class); assertThat(imports).hasSize(getAutoConfigurationClassNames().size() - 2); assertThat(ConditionEvaluationReport.get(this.beanFactory).getExclusions()) .contains(FreeMarkerAutoConfiguration.class.getName(), @@ -129,12 +132,11 @@ public class EnableAutoConfigurationImportSelectorTests { @Test public void severalPropertyYamlExclusionsAreApplied() { - configureExclusions(new String[0], new String[0], new String[0]); this.environment.setProperty("spring.autoconfigure.exclude[0]", FreeMarkerAutoConfiguration.class.getName()); this.environment.setProperty("spring.autoconfigure.exclude[1]", MustacheAutoConfiguration.class.getName()); - String[] imports = this.importSelector.selectImports(this.annotationMetadata); + String[] imports = selectImports(BasicEnableAutoConfiguration.class); assertThat(imports).hasSize(getAutoConfigurationClassNames().size() - 2); assertThat(ConditionEvaluationReport.get(this.beanFactory).getExclusions()) .contains(FreeMarkerAutoConfiguration.class.getName(), @@ -143,10 +145,10 @@ public class EnableAutoConfigurationImportSelectorTests { @Test public void combinedExclusionsAreApplied() { - configureExclusions(new String[] { MustacheAutoConfiguration.class.getName() }, - new String[] { FreeMarkerAutoConfiguration.class.getName() }, - new String[] { ThymeleafAutoConfiguration.class.getName() }); - String[] imports = this.importSelector.selectImports(this.annotationMetadata); + this.environment.setProperty("spring.autoconfigure.exclude", + ThymeleafAutoConfiguration.class.getName()); + String[] imports = selectImports( + EnableAutoConfigurationWithClassAndClassNameExclusions.class); assertThat(imports).hasSize(getAutoConfigurationClassNames().size() - 3); assertThat(ConditionEvaluationReport.get(this.beanFactory).getExclusions()) .contains(FreeMarkerAutoConfiguration.class.getName(), @@ -156,79 +158,58 @@ public class EnableAutoConfigurationImportSelectorTests { @Test public void propertyOverrideSetToTrue() throws Exception { - configureExclusions(new String[0], new String[0], new String[0]); this.environment.setProperty(EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, "true"); - String[] imports = this.importSelector.selectImports(this.annotationMetadata); + String[] imports = selectImports(BasicEnableAutoConfiguration.class); assertThat(imports).isNotEmpty(); } @Test public void propertyOverrideSetToFalse() throws Exception { - configureExclusions(new String[0], new String[0], new String[0]); this.environment.setProperty(EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, "false"); - String[] imports = this.importSelector.selectImports(this.annotationMetadata); + String[] imports = selectImports(BasicEnableAutoConfiguration.class); assertThat(imports).isEmpty(); } @Test public void nonAutoConfigurationClassExclusionsShouldThrowException() throws Exception { - configureExclusions(new String[] { TestConfiguration.class.getName() }, - new String[0], new String[0]); this.expected.expect(IllegalStateException.class); - this.importSelector.selectImports(this.annotationMetadata); + selectImports(EnableAutoConfigurationWithFaultyClassExclude.class); } @Test public void nonAutoConfigurationClassNameExclusionsWhenPresentOnClassPathShouldThrowException() throws Exception { - configureExclusions(new String[0], - new String[] { "org.springframework.boot.autoconfigure." - + "EnableAutoConfigurationImportSelectorTests.TestConfiguration" }, - new String[0]); this.expected.expect(IllegalStateException.class); - this.importSelector.selectImports(this.annotationMetadata); + selectImports(EnableAutoConfigurationWithFaultyClassNameExclude.class); } @Test public void nonAutoConfigurationPropertyExclusionsWhenPresentOnClassPathShouldThrowException() throws Exception { - configureExclusions(new String[0], new String[0], - new String[] { "org.springframework.boot.autoconfigure." - + "EnableAutoConfigurationImportSelectorTests.TestConfiguration" }); + this.environment.setProperty("spring.autoconfigure.exclude", + "org.springframework.boot.autoconfigure." + + "EnableAutoConfigurationImportSelectorTests.TestConfiguration"); this.expected.expect(IllegalStateException.class); - this.importSelector.selectImports(this.annotationMetadata); + selectImports(BasicEnableAutoConfiguration.class); } @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"); + this.environment.setProperty("spring.autoconfigure.exclude", + "org.springframework.boot.autoconfigure.DoesNotExist2"); + selectImports(EnableAutoConfigurationWithAbsentClassNameExclude.class); assertThat(ConditionEvaluationReport.get(this.beanFactory).getExclusions()) - .contains("org.springframework.boot.autoconfigure.DoesNotExist2"); + .containsExactlyInAnyOrder( + "org.springframework.boot.autoconfigure.DoesNotExist1", + "org.springframework.boot.autoconfigure.DoesNotExist2"); } - private void configureExclusions(String[] classExclusion, String[] nameExclusion, - String[] propertyExclusion) { - String annotationName = EnableAutoConfiguration.class.getName(); - given(this.annotationMetadata.isAnnotated(annotationName)).willReturn(true); - given(this.annotationMetadata.getAnnotationAttributes(annotationName, true)) - .willReturn(this.annotationAttributes); - given(this.annotationAttributes.getStringArray("exclude")) - .willReturn(classExclusion); - given(this.annotationAttributes.getStringArray("excludeName")) - .willReturn(nameExclusion); - if (propertyExclusion.length > 0) { - String value = StringUtils.arrayToCommaDelimitedString(propertyExclusion); - this.environment.setProperty("spring.autoconfigure.exclude", value); - } + private String[] selectImports(Class source) { + return this.importSelector.selectImports(new StandardAnnotationMetadata(source)); } private List getAutoConfigurationClassNames() { @@ -241,4 +222,49 @@ public class EnableAutoConfigurationImportSelectorTests { } + @EnableAutoConfiguration + private class BasicEnableAutoConfiguration { + + } + + @EnableAutoConfiguration(exclude = FreeMarkerAutoConfiguration.class) + private class EnableAutoConfigurationWithClassExclusions { + + } + + @SpringBootApplication(exclude = FreeMarkerAutoConfiguration.class) + private class SpringBootApplicationWithClassExclusions { + + } + + @EnableAutoConfiguration(excludeName = "org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration") + private class EnableAutoConfigurationWithClassNameExclusions { + + } + + @EnableAutoConfiguration(exclude = MustacheAutoConfiguration.class, excludeName = "org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration") + private class EnableAutoConfigurationWithClassAndClassNameExclusions { + + } + + @EnableAutoConfiguration(exclude = TestConfiguration.class) + private class EnableAutoConfigurationWithFaultyClassExclude { + + } + + @EnableAutoConfiguration(excludeName = "org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelectorTests.TestConfiguration") + private class EnableAutoConfigurationWithFaultyClassNameExclude { + + } + + @EnableAutoConfiguration(excludeName = "org.springframework.boot.autoconfigure.DoesNotExist1") + private class EnableAutoConfigurationWithAbsentClassNameExclude { + + } + + @SpringBootApplication(excludeName = "org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration") + private class SpringBootApplicationWithClassNameExclusions { + + } + }