Rename EnableAutoConfigurationImportSelector
Rename EnableAutoConfigurationImportSelector to the more general AutoConfigurationImportSelector since it's now used for more than just the enable annotation. The existing EnableAutoConfigurationImportSelector class remains in a deprecated form so that it can be made package-private again in Spring Boot 2.0. Fixes gh-8072
This commit is contained in:
parent
2c89d9918f
commit
b225b7f33a
|
|
@ -0,0 +1,315 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.boot.autoconfigure;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||||
|
import org.springframework.beans.factory.BeanFactory;
|
||||||
|
import org.springframework.beans.factory.BeanFactoryAware;
|
||||||
|
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||||
|
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport;
|
||||||
|
import org.springframework.boot.bind.PropertySourcesPropertyValues;
|
||||||
|
import org.springframework.boot.bind.RelaxedDataBinder;
|
||||||
|
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.env.ConfigurableEnvironment;
|
||||||
|
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;
|
||||||
|
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
|
||||||
|
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link DeferredImportSelector} to handle {@link EnableAutoConfiguration
|
||||||
|
* auto-configuration}. This class can also be subclassed if a custom variant of
|
||||||
|
* {@link EnableAutoConfiguration @EnableAutoConfiguration}. is needed.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
* @author Stephane Nicoll
|
||||||
|
* @author Madhura Bhave
|
||||||
|
* @since 1.3.0
|
||||||
|
* @see EnableAutoConfiguration
|
||||||
|
*/
|
||||||
|
public class AutoConfigurationImportSelector
|
||||||
|
implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,
|
||||||
|
BeanFactoryAware, EnvironmentAware, Ordered {
|
||||||
|
|
||||||
|
private static final String[] NO_IMPORTS = {};
|
||||||
|
|
||||||
|
private ConfigurableListableBeanFactory beanFactory;
|
||||||
|
|
||||||
|
private Environment environment;
|
||||||
|
|
||||||
|
private ClassLoader beanClassLoader;
|
||||||
|
|
||||||
|
private ResourceLoader resourceLoader;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] selectImports(AnnotationMetadata metadata) {
|
||||||
|
if (!isEnabled(metadata)) {
|
||||||
|
return NO_IMPORTS;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
AnnotationAttributes attributes = getAttributes(metadata);
|
||||||
|
List<String> configurations = getCandidateConfigurations(metadata,
|
||||||
|
attributes);
|
||||||
|
configurations = removeDuplicates(configurations);
|
||||||
|
Set<String> exclusions = getExclusions(metadata, attributes);
|
||||||
|
checkExcludedClasses(configurations, exclusions);
|
||||||
|
configurations.removeAll(exclusions);
|
||||||
|
configurations = sort(configurations);
|
||||||
|
recordWithConditionEvaluationReport(configurations, exclusions);
|
||||||
|
return configurations.toArray(new String[configurations.size()]);
|
||||||
|
}
|
||||||
|
catch (IOException ex) {
|
||||||
|
throw new IllegalStateException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isEnabled(AnnotationMetadata metadata) {
|
||||||
|
if (getClass().equals(AutoConfigurationImportSelector.class)) {
|
||||||
|
return this.environment.getProperty(
|
||||||
|
EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class,
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the appropriate {@link AnnotationAttributes} from the
|
||||||
|
* {@link AnnotationMetadata}. By default this method will return attributes for
|
||||||
|
* {@link #getAnnotationClass()}.
|
||||||
|
* @param metadata the annotation metadata
|
||||||
|
* @return annotation attributes
|
||||||
|
*/
|
||||||
|
protected AnnotationAttributes getAttributes(AnnotationMetadata metadata) {
|
||||||
|
String name = getAnnotationClass().getName();
|
||||||
|
AnnotationAttributes attributes = AnnotationAttributes
|
||||||
|
.fromMap(metadata.getAnnotationAttributes(name, true));
|
||||||
|
Assert.notNull(attributes,
|
||||||
|
"No auto-configuration attributes found. Is " + metadata.getClassName()
|
||||||
|
+ " annotated with " + ClassUtils.getShortName(name) + "?");
|
||||||
|
return attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the source annotation class used by the selector.
|
||||||
|
* @return the annotation class
|
||||||
|
*/
|
||||||
|
protected Class<?> getAnnotationClass() {
|
||||||
|
return EnableAutoConfiguration.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the auto-configuration class names that should be considered. By default
|
||||||
|
* this method will load candidates using {@link SpringFactoriesLoader} with
|
||||||
|
* {@link #getSpringFactoriesLoaderFactoryClass()}.
|
||||||
|
* @param metadata the source metadata
|
||||||
|
* @param attributes the {@link #getAttributes(AnnotationMetadata) annotation
|
||||||
|
* attributes}
|
||||||
|
* @return a list of candidate configurations
|
||||||
|
*/
|
||||||
|
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
|
||||||
|
AnnotationAttributes attributes) {
|
||||||
|
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
|
||||||
|
getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
|
||||||
|
Assert.notEmpty(configurations,
|
||||||
|
"No auto configuration classes found in META-INF/spring.factories. If you "
|
||||||
|
+ "are using a custom packaging, make sure that file is correct.");
|
||||||
|
return configurations;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the class used by {@link SpringFactoriesLoader} to load configuration
|
||||||
|
* candidates.
|
||||||
|
* @return the factory class
|
||||||
|
*/
|
||||||
|
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
|
||||||
|
return EnableAutoConfiguration.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkExcludedClasses(List<String> configurations,
|
||||||
|
Set<String> exclusions) {
|
||||||
|
List<String> invalidExcludes = new ArrayList<String>();
|
||||||
|
for (String exclusion : exclusions) {
|
||||||
|
if (ClassUtils.isPresent(exclusion, getClass().getClassLoader())
|
||||||
|
&& !configurations.contains(exclusion)) {
|
||||||
|
invalidExcludes.add(exclusion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!invalidExcludes.isEmpty()) {
|
||||||
|
handleInvalidExcludes(invalidExcludes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle any invalid excludes that have been specified.
|
||||||
|
* @param invalidExcludes the list of invalid excludes (will always have at least one
|
||||||
|
* element)
|
||||||
|
*/
|
||||||
|
protected void handleInvalidExcludes(List<String> invalidExcludes) {
|
||||||
|
StringBuilder message = new StringBuilder();
|
||||||
|
for (String exclude : invalidExcludes) {
|
||||||
|
message.append("\t- ").append(exclude).append(String.format("%n"));
|
||||||
|
}
|
||||||
|
throw new IllegalStateException(String
|
||||||
|
.format("The following classes could not be excluded because they are"
|
||||||
|
+ " not auto-configuration classes:%n%s", message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return any exclusions that limit the candidate configurations.
|
||||||
|
* @param metadata the source metadata
|
||||||
|
* @param attributes the {@link #getAttributes(AnnotationMetadata) annotation
|
||||||
|
* attributes}
|
||||||
|
* @return exclusions or an empty set
|
||||||
|
*/
|
||||||
|
protected Set<String> getExclusions(AnnotationMetadata metadata,
|
||||||
|
AnnotationAttributes attributes) {
|
||||||
|
Set<String> excluded = new LinkedHashSet<String>();
|
||||||
|
excluded.addAll(asList(attributes, "exclude"));
|
||||||
|
excluded.addAll(Arrays.asList(attributes.getStringArray("excludeName")));
|
||||||
|
excluded.addAll(getExcludeAutoConfigurationsProperty());
|
||||||
|
return excluded;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getExcludeAutoConfigurationsProperty() {
|
||||||
|
if (getEnvironment() instanceof ConfigurableEnvironment) {
|
||||||
|
Excludes excludes = new Excludes();
|
||||||
|
RelaxedDataBinder binder = new RelaxedDataBinder(excludes,
|
||||||
|
"spring.autoconfigure.");
|
||||||
|
binder.bind(new PropertySourcesPropertyValues(
|
||||||
|
((ConfigurableEnvironment) getEnvironment()).getPropertySources()));
|
||||||
|
return excludes.getExclude();
|
||||||
|
}
|
||||||
|
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(getEnvironment(),
|
||||||
|
"spring.autoconfigure.");
|
||||||
|
String[] exclude = resolver.getProperty("exclude", String[].class);
|
||||||
|
return (Arrays.asList(exclude == null ? new String[0] : exclude));
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> sort(List<String> configurations) throws IOException {
|
||||||
|
configurations = new AutoConfigurationSorter(getMetadataReaderFactory())
|
||||||
|
.getInPriorityOrder(configurations);
|
||||||
|
return configurations;
|
||||||
|
}
|
||||||
|
|
||||||
|
private MetadataReaderFactory getMetadataReaderFactory() {
|
||||||
|
try {
|
||||||
|
return getBeanFactory().getBean(
|
||||||
|
SharedMetadataReaderFactoryContextInitializer.BEAN_NAME,
|
||||||
|
MetadataReaderFactory.class);
|
||||||
|
}
|
||||||
|
catch (NoSuchBeanDefinitionException ex) {
|
||||||
|
return new CachingMetadataReaderFactory(this.resourceLoader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void recordWithConditionEvaluationReport(List<String> configurations,
|
||||||
|
Collection<String> exclusions) throws IOException {
|
||||||
|
ConditionEvaluationReport report = ConditionEvaluationReport
|
||||||
|
.get(getBeanFactory());
|
||||||
|
report.recordEvaluationCandidates(configurations);
|
||||||
|
report.recordExclusions(exclusions);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final <T> List<T> removeDuplicates(List<T> list) {
|
||||||
|
return new ArrayList<T>(new LinkedHashSet<T>(list));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final List<String> asList(AnnotationAttributes attributes, String name) {
|
||||||
|
String[] value = attributes.getStringArray(name);
|
||||||
|
return Arrays.asList(value == null ? new String[0] : value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||||
|
Assert.isInstanceOf(ConfigurableListableBeanFactory.class, beanFactory);
|
||||||
|
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final ConfigurableListableBeanFactory getBeanFactory() {
|
||||||
|
return this.beanFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||||
|
this.beanClassLoader = classLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ClassLoader getBeanClassLoader() {
|
||||||
|
return this.beanClassLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEnvironment(Environment environment) {
|
||||||
|
this.environment = environment;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final Environment getEnvironment() {
|
||||||
|
return this.environment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setResourceLoader(ResourceLoader resourceLoader) {
|
||||||
|
this.resourceLoader = resourceLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final ResourceLoader getResourceLoader() {
|
||||||
|
return this.resourceLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOrder() {
|
||||||
|
return Ordered.LOWEST_PRECEDENCE - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bindable object used to get excludes.
|
||||||
|
*/
|
||||||
|
static class Excludes {
|
||||||
|
|
||||||
|
private List<String> exclude = new ArrayList<String>();
|
||||||
|
|
||||||
|
public List<String> getExclude() {
|
||||||
|
return this.exclude;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExclude(List<String> excludes) {
|
||||||
|
this.exclude = excludes;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -67,6 +67,7 @@ import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||||
* @see ConditionalOnClass
|
* @see ConditionalOnClass
|
||||||
* @see AutoConfigureAfter
|
* @see AutoConfigureAfter
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
@Target(ElementType.TYPE)
|
@Target(ElementType.TYPE)
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Documented
|
@Documented
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -16,44 +16,15 @@
|
||||||
|
|
||||||
package org.springframework.boot.autoconfigure;
|
package org.springframework.boot.autoconfigure;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.springframework.beans.BeansException;
|
|
||||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
|
||||||
import org.springframework.beans.factory.BeanFactory;
|
|
||||||
import org.springframework.beans.factory.BeanFactoryAware;
|
|
||||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
|
||||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport;
|
|
||||||
import org.springframework.boot.bind.PropertySourcesPropertyValues;
|
|
||||||
import org.springframework.boot.bind.RelaxedDataBinder;
|
|
||||||
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.context.annotation.DeferredImportSelector;
|
||||||
import org.springframework.core.Ordered;
|
|
||||||
import org.springframework.core.annotation.AnnotationAttributes;
|
|
||||||
import org.springframework.core.env.ConfigurableEnvironment;
|
|
||||||
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;
|
import org.springframework.core.type.AnnotationMetadata;
|
||||||
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
|
|
||||||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.util.ClassUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link DeferredImportSelector} to handle {@link EnableAutoConfiguration
|
* {@link DeferredImportSelector} to handle {@link EnableAutoConfiguration
|
||||||
* auto-configuration}. This class can also be subclassed if a custom variant of
|
* auto-configuration}. This class can also be subclassed if a custom variant of
|
||||||
* {@link EnableAutoConfiguration @EnableAutoConfiguration}. is needed.
|
* {@link EnableAutoConfiguration @EnableAutoConfiguration}. is needed.
|
||||||
*
|
*
|
||||||
|
* @deprecated as of 1.5 in favor of {@link AutoConfigurationImportSelector}
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
|
@ -61,255 +32,18 @@ import org.springframework.util.ClassUtils;
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
* @see EnableAutoConfiguration
|
* @see EnableAutoConfiguration
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public class EnableAutoConfigurationImportSelector
|
public class EnableAutoConfigurationImportSelector
|
||||||
implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,
|
extends AutoConfigurationImportSelector {
|
||||||
BeanFactoryAware, EnvironmentAware, Ordered {
|
|
||||||
|
|
||||||
private static final String[] NO_IMPORTS = {};
|
|
||||||
|
|
||||||
private ConfigurableListableBeanFactory beanFactory;
|
|
||||||
|
|
||||||
private Environment environment;
|
|
||||||
|
|
||||||
private ClassLoader beanClassLoader;
|
|
||||||
|
|
||||||
private ResourceLoader resourceLoader;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] selectImports(AnnotationMetadata metadata) {
|
|
||||||
if (!isEnabled(metadata)) {
|
|
||||||
return NO_IMPORTS;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
AnnotationAttributes attributes = getAttributes(metadata);
|
|
||||||
List<String> configurations = getCandidateConfigurations(metadata,
|
|
||||||
attributes);
|
|
||||||
configurations = removeDuplicates(configurations);
|
|
||||||
Set<String> exclusions = getExclusions(metadata, attributes);
|
|
||||||
checkExcludedClasses(configurations, exclusions);
|
|
||||||
configurations.removeAll(exclusions);
|
|
||||||
configurations = sort(configurations);
|
|
||||||
recordWithConditionEvaluationReport(configurations, exclusions);
|
|
||||||
return configurations.toArray(new String[configurations.size()]);
|
|
||||||
}
|
|
||||||
catch (IOException ex) {
|
|
||||||
throw new IllegalStateException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean isEnabled(AnnotationMetadata metadata) {
|
protected boolean isEnabled(AnnotationMetadata metadata) {
|
||||||
if (getClass().equals(EnableAutoConfigurationImportSelector.class)) {
|
if (getClass().equals(EnableAutoConfigurationImportSelector.class)) {
|
||||||
return this.environment.getProperty(
|
return getEnvironment().getProperty(
|
||||||
EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class,
|
EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class,
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the appropriate {@link AnnotationAttributes} from the
|
|
||||||
* {@link AnnotationMetadata}. By default this method will return attributes for
|
|
||||||
* {@link #getAnnotationClass()}.
|
|
||||||
* @param metadata the annotation metadata
|
|
||||||
* @return annotation attributes
|
|
||||||
*/
|
|
||||||
protected AnnotationAttributes getAttributes(AnnotationMetadata metadata) {
|
|
||||||
String name = getAnnotationClass().getName();
|
|
||||||
AnnotationAttributes attributes = AnnotationAttributes
|
|
||||||
.fromMap(metadata.getAnnotationAttributes(name, true));
|
|
||||||
Assert.notNull(attributes,
|
|
||||||
"No auto-configuration attributes found. Is " + metadata.getClassName()
|
|
||||||
+ " annotated with " + ClassUtils.getShortName(name) + "?");
|
|
||||||
return attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the source annotation class used by the selector.
|
|
||||||
* @return the annotation class
|
|
||||||
*/
|
|
||||||
protected Class<?> getAnnotationClass() {
|
|
||||||
return EnableAutoConfiguration.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the auto-configuration class names that should be considered. By default
|
|
||||||
* this method will load candidates using {@link SpringFactoriesLoader} with
|
|
||||||
* {@link #getSpringFactoriesLoaderFactoryClass()}.
|
|
||||||
* @param metadata the source metadata
|
|
||||||
* @param attributes the {@link #getAttributes(AnnotationMetadata) annotation
|
|
||||||
* attributes}
|
|
||||||
* @return a list of candidate configurations
|
|
||||||
*/
|
|
||||||
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
|
|
||||||
AnnotationAttributes attributes) {
|
|
||||||
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
|
|
||||||
getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
|
|
||||||
Assert.notEmpty(configurations,
|
|
||||||
"No auto configuration classes found in META-INF/spring.factories. If you "
|
|
||||||
+ "are using a custom packaging, make sure that file is correct.");
|
|
||||||
return configurations;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the class used by {@link SpringFactoriesLoader} to load configuration
|
|
||||||
* candidates.
|
|
||||||
* @return the factory class
|
|
||||||
*/
|
|
||||||
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
|
|
||||||
return EnableAutoConfiguration.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkExcludedClasses(List<String> configurations,
|
|
||||||
Set<String> exclusions) {
|
|
||||||
List<String> invalidExcludes = new ArrayList<String>();
|
|
||||||
for (String exclusion : exclusions) {
|
|
||||||
if (ClassUtils.isPresent(exclusion, getClass().getClassLoader())
|
|
||||||
&& !configurations.contains(exclusion)) {
|
|
||||||
invalidExcludes.add(exclusion);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!invalidExcludes.isEmpty()) {
|
|
||||||
handleInvalidExcludes(invalidExcludes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle any invalid excludes that have been specified.
|
|
||||||
* @param invalidExcludes the list of invalid excludes (will always have at least one
|
|
||||||
* element)
|
|
||||||
*/
|
|
||||||
protected void handleInvalidExcludes(List<String> invalidExcludes) {
|
|
||||||
StringBuilder message = new StringBuilder();
|
|
||||||
for (String exclude : invalidExcludes) {
|
|
||||||
message.append("\t- ").append(exclude).append(String.format("%n"));
|
|
||||||
}
|
|
||||||
throw new IllegalStateException(String
|
|
||||||
.format("The following classes could not be excluded because they are"
|
|
||||||
+ " not auto-configuration classes:%n%s", message));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return any exclusions that limit the candidate configurations.
|
|
||||||
* @param metadata the source metadata
|
|
||||||
* @param attributes the {@link #getAttributes(AnnotationMetadata) annotation
|
|
||||||
* attributes}
|
|
||||||
* @return exclusions or an empty set
|
|
||||||
*/
|
|
||||||
protected Set<String> getExclusions(AnnotationMetadata metadata,
|
|
||||||
AnnotationAttributes attributes) {
|
|
||||||
Set<String> excluded = new LinkedHashSet<String>();
|
|
||||||
excluded.addAll(asList(attributes, "exclude"));
|
|
||||||
excluded.addAll(Arrays.asList(attributes.getStringArray("excludeName")));
|
|
||||||
excluded.addAll(getExcludeAutoConfigurationsProperty());
|
|
||||||
return excluded;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> getExcludeAutoConfigurationsProperty() {
|
|
||||||
if (getEnvironment() instanceof ConfigurableEnvironment) {
|
|
||||||
Excludes excludes = new Excludes();
|
|
||||||
RelaxedDataBinder binder = new RelaxedDataBinder(excludes,
|
|
||||||
"spring.autoconfigure.");
|
|
||||||
binder.bind(new PropertySourcesPropertyValues(
|
|
||||||
((ConfigurableEnvironment) getEnvironment()).getPropertySources()));
|
|
||||||
return excludes.getExclude();
|
|
||||||
}
|
|
||||||
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(getEnvironment(),
|
|
||||||
"spring.autoconfigure.");
|
|
||||||
String[] exclude = resolver.getProperty("exclude", String[].class);
|
|
||||||
return (Arrays.asList(exclude == null ? new String[0] : exclude));
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> sort(List<String> configurations) throws IOException {
|
|
||||||
configurations = new AutoConfigurationSorter(getMetadataReaderFactory())
|
|
||||||
.getInPriorityOrder(configurations);
|
|
||||||
return configurations;
|
|
||||||
}
|
|
||||||
|
|
||||||
private MetadataReaderFactory getMetadataReaderFactory() {
|
|
||||||
try {
|
|
||||||
return getBeanFactory().getBean(
|
|
||||||
SharedMetadataReaderFactoryContextInitializer.BEAN_NAME,
|
|
||||||
MetadataReaderFactory.class);
|
|
||||||
}
|
|
||||||
catch (NoSuchBeanDefinitionException ex) {
|
|
||||||
return new CachingMetadataReaderFactory(this.resourceLoader);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void recordWithConditionEvaluationReport(List<String> configurations,
|
|
||||||
Collection<String> exclusions) throws IOException {
|
|
||||||
ConditionEvaluationReport report = ConditionEvaluationReport
|
|
||||||
.get(getBeanFactory());
|
|
||||||
report.recordEvaluationCandidates(configurations);
|
|
||||||
report.recordExclusions(exclusions);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final <T> List<T> removeDuplicates(List<T> list) {
|
|
||||||
return new ArrayList<T>(new LinkedHashSet<T>(list));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final List<String> asList(AnnotationAttributes attributes, String name) {
|
|
||||||
String[] value = attributes.getStringArray(name);
|
|
||||||
return Arrays.asList(value == null ? new String[0] : value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
|
||||||
Assert.isInstanceOf(ConfigurableListableBeanFactory.class, beanFactory);
|
|
||||||
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final ConfigurableListableBeanFactory getBeanFactory() {
|
|
||||||
return this.beanFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
|
||||||
this.beanClassLoader = classLoader;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ClassLoader getBeanClassLoader() {
|
|
||||||
return this.beanClassLoader;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setEnvironment(Environment environment) {
|
|
||||||
this.environment = environment;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final Environment getEnvironment() {
|
|
||||||
return this.environment;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setResourceLoader(ResourceLoader resourceLoader) {
|
|
||||||
this.resourceLoader = resourceLoader;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final ResourceLoader getResourceLoader() {
|
|
||||||
return this.resourceLoader;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getOrder() {
|
|
||||||
return Ordered.LOWEST_PRECEDENCE - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bindable object used to get excludes.
|
|
||||||
*/
|
|
||||||
static class Excludes {
|
|
||||||
|
|
||||||
private List<String> exclude = new ArrayList<String>();
|
|
||||||
|
|
||||||
public List<String> getExclude() {
|
|
||||||
return this.exclude;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExclude(List<String> excludes) {
|
|
||||||
this.exclude = excludes;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -44,8 +44,7 @@ import org.springframework.util.ObjectUtils;
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
*/
|
*/
|
||||||
class ImportAutoConfigurationImportSelector
|
class ImportAutoConfigurationImportSelector extends AutoConfigurationImportSelector {
|
||||||
extends EnableAutoConfigurationImportSelector {
|
|
||||||
|
|
||||||
private static final Set<String> ANNOTATION_NAMES;
|
private static final Set<String> ANNOTATION_NAMES;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -39,15 +39,15 @@ import org.springframework.mock.env.MockEnvironment;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link EnableAutoConfigurationImportSelector}
|
* Tests for {@link AutoConfigurationImportSelector}
|
||||||
*
|
*
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
* @author Madhura Bhave
|
* @author Madhura Bhave
|
||||||
*/
|
*/
|
||||||
public class EnableAutoConfigurationImportSelectorTests {
|
public class AutoConfigurationImportSelectorTests {
|
||||||
|
|
||||||
private final EnableAutoConfigurationImportSelector importSelector = new EnableAutoConfigurationImportSelector();
|
private final AutoConfigurationImportSelector importSelector = new AutoConfigurationImportSelector();
|
||||||
|
|
||||||
private final ConfigurableListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
private final ConfigurableListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||||
|
|
||||||
|
|
@ -191,7 +191,7 @@ public class EnableAutoConfigurationImportSelectorTests {
|
||||||
throws Exception {
|
throws Exception {
|
||||||
this.environment.setProperty("spring.autoconfigure.exclude",
|
this.environment.setProperty("spring.autoconfigure.exclude",
|
||||||
"org.springframework.boot.autoconfigure."
|
"org.springframework.boot.autoconfigure."
|
||||||
+ "EnableAutoConfigurationImportSelectorTests.TestConfiguration");
|
+ "AutoConfigurationImportSelectorTests.TestConfiguration");
|
||||||
this.expected.expect(IllegalStateException.class);
|
this.expected.expect(IllegalStateException.class);
|
||||||
selectImports(BasicEnableAutoConfiguration.class);
|
selectImports(BasicEnableAutoConfiguration.class);
|
||||||
}
|
}
|
||||||
|
|
@ -252,7 +252,7 @@ public class EnableAutoConfigurationImportSelectorTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@EnableAutoConfiguration(excludeName = "org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelectorTests.TestConfiguration")
|
@EnableAutoConfiguration(excludeName = "org.springframework.boot.autoconfigure.AutoConfigurationImportSelectorTests.TestConfiguration")
|
||||||
private class EnableAutoConfigurationWithFaultyClassNameExclude {
|
private class EnableAutoConfigurationWithFaultyClassNameExclude {
|
||||||
|
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue