Add `include` support to @EnableAutoConfiguration

Update the `@EnableAutoConfiguration` annotation to include an `include`
attribute which can be used to specify specific auto-configuration
classes.

Primarily added to so that tests can selectively auto-configure without
needing to worry about class import order.

Fixes gh-3660
pull/3555/merge
Phillip Webb 9 years ago
parent a10bfc153d
commit 1d31d23e29

@ -75,6 +75,15 @@ import org.springframework.core.io.support.SpringFactoriesLoader;
AutoConfigurationPackages.Registrar.class })
public @interface EnableAutoConfiguration {
/**
* Include only the specified auto-configuration classes and do not attempt full
* auto-configuration. Using this attribute means that {@code spring.factories} files
* will not be considered. This attribute should not generally be specified in
* production applications, however, it is useful for tests.
* @return the classes to include
*/
Class<?>[] include() default {};
/**
* Exclude specific auto-configuration classes such that they will never be applied.
* @return the classes to exclude

@ -75,14 +75,12 @@ class EnableAutoConfigurationImportSelector implements DeferredImportSelector,
+ " annotated with @EnableAutoConfiguration?");
// Find all possible auto configuration classes, filtering duplicates
List<String> factories = new ArrayList<String>(new LinkedHashSet<String>(
SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class,
this.beanClassLoader)));
List<String> factories = getFactories(attributes);
// Remove those specifically excluded
Set<String> excluded = new LinkedHashSet<String>();
excluded.addAll(Arrays.asList(attributes.getStringArray("exclude")));
excluded.addAll(Arrays.asList(attributes.getStringArray("excludeName")));
excluded.addAll(asList(attributes, "exclude"));
excluded.addAll(asList(attributes, "excludeName"));
excluded.addAll(getExcludeAutoConfigurationsProperty());
factories.removeAll(excluded);
ConditionEvaluationReport.get(this.beanFactory).recordExclusions(excluded);
@ -100,6 +98,20 @@ class EnableAutoConfigurationImportSelector implements DeferredImportSelector,
}
}
private List<String> getFactories(AnnotationAttributes attributes) {
List<String> factories = asList(attributes, "include");
if (factories.isEmpty()) {
factories = SpringFactoriesLoader.loadFactoryNames(
EnableAutoConfiguration.class, this.beanClassLoader);
}
return new ArrayList<String>(new LinkedHashSet<String>(factories));
}
private List<String> asList(AnnotationAttributes attributes, String name) {
String[] value = attributes.getStringArray(name);
return Arrays.asList(value == null ? new String[0] : value);
}
private List<String> getExcludeAutoConfigurationsProperty() {
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(this.environment,
"spring.autoconfigure.");

@ -148,6 +148,18 @@ public class EnableAutoConfigurationImportSelectorTests {
ThymeleafAutoConfiguration.class.getName()));
}
@Test
public void classIncludesAreApplied() throws Exception {
given(
this.annotationMetadata.getAnnotationAttributes(
EnableAutoConfiguration.class.getName(), true)).willReturn(
this.annotationAttributes);
given(this.annotationAttributes.getStringArray("include")).willReturn(
new String[] { FreeMarkerAutoConfiguration.class.getName() });
String[] imports = this.importSelector.selectImports(this.annotationMetadata);
assertThat(imports.length, is(equalTo(1)));
}
private void configureExclusions(String[] classExclusion, String[] nameExclusion,
String[] propertyExclusion) {
given(
@ -168,4 +180,5 @@ public class EnableAutoConfigurationImportSelectorTests {
return SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class,
getClass().getClassLoader());
}
}

@ -18,9 +18,11 @@ package org.springframework.boot.autoconfigure.context;
import org.junit.After;
import org.junit.Test;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.test.EnvironmentTestUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import static org.hamcrest.core.Is.is;
@ -44,8 +46,7 @@ public class ConfigurationPropertiesAutoConfigurationTests {
@Test
public void processAnnotatedBean() {
load(new Class[] { SampleBean.class,
ConfigurationPropertiesAutoConfiguration.class }, "foo.name:test");
load(new Class[] { AutoConfigured.class, SampleBean.class }, "foo.name:test");
assertThat(this.context.getBean(SampleBean.class).getName(), is("test"));
}
@ -62,6 +63,12 @@ public class ConfigurationPropertiesAutoConfigurationTests {
this.context.refresh();
}
@Configuration
@EnableAutoConfiguration(include = ConfigurationPropertiesAutoConfiguration.class)
static class AutoConfigured {
}
@Component
@ConfigurationProperties("foo")
static class SampleBean {

Loading…
Cancel
Save