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
This commit is contained in:
parent
a10bfc153d
commit
1d31d23e29
|
|
@ -75,6 +75,15 @@ import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||||
AutoConfigurationPackages.Registrar.class })
|
AutoConfigurationPackages.Registrar.class })
|
||||||
public @interface EnableAutoConfiguration {
|
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.
|
* Exclude specific auto-configuration classes such that they will never be applied.
|
||||||
* @return the classes to exclude
|
* @return the classes to exclude
|
||||||
|
|
|
||||||
|
|
@ -75,14 +75,12 @@ class EnableAutoConfigurationImportSelector implements DeferredImportSelector,
|
||||||
+ " annotated with @EnableAutoConfiguration?");
|
+ " annotated with @EnableAutoConfiguration?");
|
||||||
|
|
||||||
// Find all possible auto configuration classes, filtering duplicates
|
// Find all possible auto configuration classes, filtering duplicates
|
||||||
List<String> factories = new ArrayList<String>(new LinkedHashSet<String>(
|
List<String> factories = getFactories(attributes);
|
||||||
SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class,
|
|
||||||
this.beanClassLoader)));
|
|
||||||
|
|
||||||
// Remove those specifically excluded
|
// Remove those specifically excluded
|
||||||
Set<String> excluded = new LinkedHashSet<String>();
|
Set<String> excluded = new LinkedHashSet<String>();
|
||||||
excluded.addAll(Arrays.asList(attributes.getStringArray("exclude")));
|
excluded.addAll(asList(attributes, "exclude"));
|
||||||
excluded.addAll(Arrays.asList(attributes.getStringArray("excludeName")));
|
excluded.addAll(asList(attributes, "excludeName"));
|
||||||
excluded.addAll(getExcludeAutoConfigurationsProperty());
|
excluded.addAll(getExcludeAutoConfigurationsProperty());
|
||||||
factories.removeAll(excluded);
|
factories.removeAll(excluded);
|
||||||
ConditionEvaluationReport.get(this.beanFactory).recordExclusions(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() {
|
private List<String> getExcludeAutoConfigurationsProperty() {
|
||||||
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(this.environment,
|
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(this.environment,
|
||||||
"spring.autoconfigure.");
|
"spring.autoconfigure.");
|
||||||
|
|
|
||||||
|
|
@ -148,6 +148,18 @@ public class EnableAutoConfigurationImportSelectorTests {
|
||||||
ThymeleafAutoConfiguration.class.getName()));
|
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,
|
private void configureExclusions(String[] classExclusion, String[] nameExclusion,
|
||||||
String[] propertyExclusion) {
|
String[] propertyExclusion) {
|
||||||
given(
|
given(
|
||||||
|
|
@ -168,4 +180,5 @@ public class EnableAutoConfigurationImportSelectorTests {
|
||||||
return SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class,
|
return SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class,
|
||||||
getClass().getClassLoader());
|
getClass().getClassLoader());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,11 @@ package org.springframework.boot.autoconfigure.context;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.boot.test.EnvironmentTestUtils;
|
import org.springframework.boot.test.EnvironmentTestUtils;
|
||||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import static org.hamcrest.core.Is.is;
|
import static org.hamcrest.core.Is.is;
|
||||||
|
|
@ -44,8 +46,7 @@ public class ConfigurationPropertiesAutoConfigurationTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void processAnnotatedBean() {
|
public void processAnnotatedBean() {
|
||||||
load(new Class[] { SampleBean.class,
|
load(new Class[] { AutoConfigured.class, SampleBean.class }, "foo.name:test");
|
||||||
ConfigurationPropertiesAutoConfiguration.class }, "foo.name:test");
|
|
||||||
assertThat(this.context.getBean(SampleBean.class).getName(), is("test"));
|
assertThat(this.context.getBean(SampleBean.class).getName(), is("test"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -62,6 +63,12 @@ public class ConfigurationPropertiesAutoConfigurationTests {
|
||||||
this.context.refresh();
|
this.context.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableAutoConfiguration(include = ConfigurationPropertiesAutoConfiguration.class)
|
||||||
|
static class AutoConfigured {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@ConfigurationProperties("foo")
|
@ConfigurationProperties("foo")
|
||||||
static class SampleBean {
|
static class SampleBean {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue