diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/EnableAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/EnableAutoConfiguration.java
index d7837380f42..dca59dca18e 100644
--- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/EnableAutoConfiguration.java
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/EnableAutoConfiguration.java
@@ -44,8 +44,9 @@ import org.springframework.core.io.support.SpringFactoriesLoader;
* Auto-configuration tries to be as intelligent as possible and will back-away as you
* define more of your own configuration. You can always manually {@link #exclude()} any
* configuration that you never want to apply (use {@link #excludeName()} if you don't
- * have access to them). Auto-configuration is always applied after user-defined beans
- * have been registered.
+ * have access to them). You can also exclude them via the
+ * {@code spring.autoconfigure.exclude} property. Auto-configuration is always applied
+ * after user-defined beans have been registered.
*
* The package of the class that is annotated with {@code @EnableAutoConfiguration} has
* specific significance and is often used as a 'default'. For example, it will be used
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 88173e63c17..d07d36cb2d8 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
@@ -19,6 +19,7 @@ package org.springframework.boot.autoconfigure;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
@@ -29,11 +30,14 @@ import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport;
+import org.springframework.boot.bind.RelaxedPropertyResolver;
+import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.DeferredImportSelector;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.annotation.Order;
+import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.core.type.AnnotationMetadata;
@@ -50,10 +54,12 @@ import org.springframework.util.Assert;
*/
@Order(Ordered.LOWEST_PRECEDENCE - 1)
class EnableAutoConfigurationImportSelector implements DeferredImportSelector,
- BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware {
+ BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware {
private ConfigurableListableBeanFactory beanFactory;
+ private Environment environment;
+
private ClassLoader beanClassLoader;
private ResourceLoader resourceLoader;
@@ -78,6 +84,7 @@ class EnableAutoConfigurationImportSelector implements DeferredImportSelector,
Set excluded = new LinkedHashSet();
excluded.addAll(Arrays.asList(attributes.getStringArray("exclude")));
excluded.addAll(Arrays.asList(attributes.getStringArray("excludeName")));
+ excluded.addAll(getExcludeAutoConfigurationsProperty());
factories.removeAll(excluded);
ConditionEvaluationReport.get(this.beanFactory).recordExclusions(excluded);
ConditionEvaluationReport.get(this.beanFactory).recordEvaluationCandidates(
@@ -94,6 +101,16 @@ class EnableAutoConfigurationImportSelector implements DeferredImportSelector,
}
}
+ private List getExcludeAutoConfigurationsProperty() {
+ RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(this.environment,
+ "spring.autoconfigure.");
+ String[] value = resolver.getProperty("exclude", String[].class);
+ if (value != null) {
+ return Arrays.asList(value);
+ }
+ return Collections.emptyList();
+ }
+
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.beanClassLoader = classLoader;
@@ -110,4 +127,9 @@ class EnableAutoConfigurationImportSelector implements DeferredImportSelector,
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
}
+ @Override
+ public void setEnvironment(Environment environment) {
+ this.environment = environment;
+ }
+
}
diff --git a/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json
index 937ad11bb59..88d30bc4a59 100644
--- a/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json
+++ b/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json
@@ -29,6 +29,11 @@
"description": "JMX name of the application admin MBean.",
"defaultValue": "org.springframework.boot:type=Admin,name=SpringApplication"
},
+ {
+ "name": "spring.autoconfigure.exclude",
+ "type": "java.lang.Class[]",
+ "description": "Auto-configuration classes to exclude."
+ },
{
"name": "spring.batch.job.enabled",
"type": "java.lang.Boolean",
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 01ce4c9c822..ac55ddb942a 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
@@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure;
import java.util.List;
+import org.flywaydb.core.internal.util.StringUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -27,11 +28,13 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport;
import org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration;
+import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration;
import org.springframework.boot.autoconfigure.velocity.VelocityAutoConfiguration;
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.mock.env.MockEnvironment;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsInAnyOrder;
@@ -54,6 +57,8 @@ public class EnableAutoConfigurationImportSelectorTests {
private final ConfigurableListableBeanFactory beanFactory = new DefaultListableBeanFactory();
+ private final MockEnvironment environment = new MockEnvironment();
+
@Mock
private AnnotationMetadata annotationMetadata;
@@ -63,12 +68,13 @@ public class EnableAutoConfigurationImportSelectorTests {
@Before
public void configureImportSelector() {
this.importSelector.setBeanFactory(this.beanFactory);
+ this.importSelector.setEnvironment(this.environment);
this.importSelector.setResourceLoader(new DefaultResourceLoader());
}
@Test
public void importsAreSelected() {
- configureExclusions(new String[0], new String[0]);
+ configureExclusions(new String[0], new String[0], new String[0]);
String[] imports = this.importSelector.selectImports(this.annotationMetadata);
assertThat(
imports.length,
@@ -82,7 +88,7 @@ public class EnableAutoConfigurationImportSelectorTests {
@Test
public void classExclusionsAreApplied() {
configureExclusions(new String[] { FreeMarkerAutoConfiguration.class.getName() },
- new String[0]);
+ new String[0], new String[0]);
String[] imports = this.importSelector.selectImports(this.annotationMetadata);
assertThat(imports.length,
is(equalTo(getAutoConfigurationClassNames().size() - 1)));
@@ -93,7 +99,7 @@ public class EnableAutoConfigurationImportSelectorTests {
@Test
public void classNamesExclusionsAreApplied() {
configureExclusions(new String[0],
- new String[] { VelocityAutoConfiguration.class.getName() });
+ new String[] { VelocityAutoConfiguration.class.getName() }, new String[0]);
String[] imports = this.importSelector.selectImports(this.annotationMetadata);
assertThat(imports.length,
is(equalTo(getAutoConfigurationClassNames().size() - 1)));
@@ -102,9 +108,22 @@ public class EnableAutoConfigurationImportSelectorTests {
}
@Test
- public void bothExclusionsAreApplied() {
- configureExclusions(new String[] { VelocityAutoConfiguration.class.getName() },
- new String[] { FreeMarkerAutoConfiguration.class.getName() });
+ public void propertyExclusionsAreApplied() {
+ configureExclusions(new String[0], new String[0], new String[] {
+ FreeMarkerAutoConfiguration.class.getName()});
+ String[] imports = this.importSelector.selectImports(this.annotationMetadata);
+ assertThat(imports.length,
+ is(equalTo(getAutoConfigurationClassNames().size() - 1)));
+ assertThat(ConditionEvaluationReport.get(this.beanFactory).getExclusions(),
+ contains(FreeMarkerAutoConfiguration.class.getName()));
+ }
+
+ @Test
+ public void severalPropertyExclusionsAreApplied() {
+ configureExclusions(new String[0], new String[0], new String[] {
+ FreeMarkerAutoConfiguration.class.getName(), VelocityAutoConfiguration
+ .class.getName()});
+
String[] imports = this.importSelector.selectImports(this.annotationMetadata);
assertThat(imports.length,
is(equalTo(getAutoConfigurationClassNames().size() - 2)));
@@ -114,7 +133,23 @@ public class EnableAutoConfigurationImportSelectorTests {
VelocityAutoConfiguration.class.getName()));
}
- private void configureExclusions(String[] classExclusion, String[] nameExclusion) {
+ @Test
+ public void combinedExclusionsAreApplied() {
+ configureExclusions(new String[] { VelocityAutoConfiguration.class.getName() },
+ new String[] { FreeMarkerAutoConfiguration.class.getName() },
+ new String[] { ThymeleafAutoConfiguration.class.getName() });
+ String[] imports = this.importSelector.selectImports(this.annotationMetadata);
+ assertThat(imports.length,
+ is(equalTo(getAutoConfigurationClassNames().size() - 3)));
+ assertThat(
+ ConditionEvaluationReport.get(this.beanFactory).getExclusions(),
+ containsInAnyOrder(FreeMarkerAutoConfiguration.class.getName(),
+ VelocityAutoConfiguration.class.getName(),
+ ThymeleafAutoConfiguration.class.getName()));
+ }
+
+ private void configureExclusions(String[] classExclusion, String[] nameExclusion,
+ String[] propertyExclusion) {
given(
this.annotationMetadata.getAnnotationAttributes(
EnableAutoConfiguration.class.getName(), true)).willReturn(
@@ -123,6 +158,11 @@ public class EnableAutoConfigurationImportSelectorTests {
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 List getAutoConfigurationClassNames() {
diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc
index 89c84312010..4a37ac3cc8f 100644
--- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc
+++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc
@@ -45,6 +45,9 @@ content into your application; rather pick only the properties that you need.
spring.main.show-banner=true
spring.main....= # see class for all properties
+ # AUTO-CONFIGURATION
+ spring.autoconfigure.exclude= # comma-separated list of auto-configuration classes to exclude
+
# ADMIN ({sc-spring-boot-autoconfigure}/admin/SpringApplicationAdminJmxAutoConfiguration.{sc-ext}[SpringApplicationAdminJmxAutoConfiguration])
spring.application.admin.enabled=false # enable admin features for the application
spring.application.admin.jmx-name=org.springframework.boot:type=Admin,name=SpringApplication # JMX name of the application admin MBean
diff --git a/spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc b/spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc
index 54c194b765a..5a7c556b3cd 100644
--- a/spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc
+++ b/spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc
@@ -602,7 +602,7 @@ report to the console.
-[[using-boot-disabling-specific-auto-configutation]]
+[[using-boot-disabling-specific-auto-configuration]]
=== Disabling specific auto-configuration
If you find that specific auto-configure classes are being applied that you don't want,
you can use the exclude attribute of `@EnableAutoConfiguration` to disable them.
@@ -619,7 +619,12 @@ you can use the exclude attribute of `@EnableAutoConfiguration` to disable them.
}
----
+If the class is not on the classpath, you can use the `excludeName` attribute of
+the annotation and specify the fully qualified name instead. Finally, you can also
+control the list of auto-configuration classes to excludes via the
+`spring.autoconfigure.exclude` property.
+TIP: You can define exclusions both at the annotation level and using the property.
[[using-boot-spring-beans-and-dependency-injection]]
== Spring Beans and dependency injection