Merge branch '2.7.x'
This commit is contained in:
commit
303979fb65
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2021 the original author or authors.
|
* Copyright 2012-2022 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,14 +16,19 @@
|
||||||
|
|
||||||
package org.springframework.boot.build.autoconfigure;
|
package org.springframework.boot.build.autoconfigure;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
@ -48,6 +53,8 @@ import org.springframework.util.StringUtils;
|
||||||
*/
|
*/
|
||||||
public class AutoConfigurationMetadata extends DefaultTask {
|
public class AutoConfigurationMetadata extends DefaultTask {
|
||||||
|
|
||||||
|
private static final String COMMENT_START = "#";
|
||||||
|
|
||||||
private SourceSet sourceSet;
|
private SourceSet sourceSet;
|
||||||
|
|
||||||
private File outputFile;
|
private File outputFile;
|
||||||
|
@ -57,6 +64,12 @@ public class AutoConfigurationMetadata extends DefaultTask {
|
||||||
.file((Callable<File>) () -> new File(this.sourceSet.getOutput().getResourcesDir(),
|
.file((Callable<File>) () -> new File(this.sourceSet.getOutput().getResourcesDir(),
|
||||||
"META-INF/spring.factories"))
|
"META-INF/spring.factories"))
|
||||||
.withPathSensitivity(PathSensitivity.RELATIVE).withPropertyName("spring.factories");
|
.withPathSensitivity(PathSensitivity.RELATIVE).withPropertyName("spring.factories");
|
||||||
|
getInputs()
|
||||||
|
.file((Callable<File>) () -> new File(this.sourceSet.getOutput().getResourcesDir(),
|
||||||
|
"META-INF/spring-boot/org.springframework.boot.autoconfigure.AutoConfiguration"))
|
||||||
|
.withPathSensitivity(PathSensitivity.RELATIVE)
|
||||||
|
.withPropertyName("org.springframework.boot.autoconfigure.AutoConfiguration");
|
||||||
|
|
||||||
dependsOn((Callable<String>) () -> this.sourceSet.getProcessResourcesTaskName());
|
dependsOn((Callable<String>) () -> this.sourceSet.getProcessResourcesTaskName());
|
||||||
getProject().getConfigurations()
|
getProject().getConfigurations()
|
||||||
.maybeCreate(AutoConfigurationPlugin.AUTO_CONFIGURATION_METADATA_CONFIGURATION_NAME);
|
.maybeCreate(AutoConfigurationPlugin.AUTO_CONFIGURATION_METADATA_CONFIGURATION_NAME);
|
||||||
|
@ -86,11 +99,9 @@ public class AutoConfigurationMetadata extends DefaultTask {
|
||||||
|
|
||||||
private Properties readAutoConfiguration() throws IOException {
|
private Properties readAutoConfiguration() throws IOException {
|
||||||
Properties autoConfiguration = CollectionFactory.createSortedProperties(true);
|
Properties autoConfiguration = CollectionFactory.createSortedProperties(true);
|
||||||
Properties springFactories = readSpringFactories(
|
Set<String> classNames = new LinkedHashSet<>();
|
||||||
new File(this.sourceSet.getOutput().getResourcesDir(), "META-INF/spring.factories"));
|
classNames.addAll(readSpringFactories());
|
||||||
String enableAutoConfiguration = springFactories
|
classNames.addAll(readAutoConfigurationsFile());
|
||||||
.getProperty("org.springframework.boot.autoconfigure.EnableAutoConfiguration");
|
|
||||||
Set<String> classNames = StringUtils.commaDelimitedListToSet(enableAutoConfiguration);
|
|
||||||
Set<String> publicClassNames = new LinkedHashSet<>();
|
Set<String> publicClassNames = new LinkedHashSet<>();
|
||||||
for (String className : classNames) {
|
for (String className : classNames) {
|
||||||
File classFile = findClassFile(className);
|
File classFile = findClassFile(className);
|
||||||
|
@ -109,6 +120,57 @@ public class AutoConfigurationMetadata extends DefaultTask {
|
||||||
return autoConfiguration;
|
return autoConfiguration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads auto-configurations from META-INF/spring.factories.
|
||||||
|
* @return auto-configurations
|
||||||
|
*/
|
||||||
|
private Set<String> readSpringFactories() throws IOException {
|
||||||
|
File file = new File(this.sourceSet.getOutput().getResourcesDir(), "META-INF/spring.factories");
|
||||||
|
if (!file.exists()) {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
Properties springFactories = readSpringFactories(file);
|
||||||
|
String enableAutoConfiguration = springFactories
|
||||||
|
.getProperty("org.springframework.boot.autoconfigure.EnableAutoConfiguration");
|
||||||
|
return StringUtils.commaDelimitedListToSet(enableAutoConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads auto-configurations from
|
||||||
|
* META-INF/spring-boot/org.springframework.boot.autoconfigure.AutoConfiguration.
|
||||||
|
* @return auto-configurations
|
||||||
|
*/
|
||||||
|
private List<String> readAutoConfigurationsFile() throws IOException {
|
||||||
|
File file = new File(this.sourceSet.getOutput().getResourcesDir(),
|
||||||
|
"META-INF/spring-boot/org.springframework.boot.autoconfigure.AutoConfiguration");
|
||||||
|
if (!file.exists()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
// Nearly identical copy of
|
||||||
|
// org.springframework.boot.autoconfigure.AutoConfigurationLoader.readAutoConfigurations
|
||||||
|
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)))) {
|
||||||
|
List<String> autoConfigurations = new ArrayList<>();
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
line = stripComment(line);
|
||||||
|
line = line.trim();
|
||||||
|
if (line.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
autoConfigurations.add(line);
|
||||||
|
}
|
||||||
|
return autoConfigurations;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String stripComment(String line) {
|
||||||
|
int commentStart = line.indexOf(COMMENT_START);
|
||||||
|
if (commentStart == -1) {
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
return line.substring(0, commentStart);
|
||||||
|
}
|
||||||
|
|
||||||
private File findClassFile(String className) {
|
private File findClassFile(String className) {
|
||||||
String classFileName = className.replace(".", "/") + ".class";
|
String classFileName = className.replace(".", "/") + ".class";
|
||||||
for (File classesDir : this.sourceSet.getOutput().getClassesDirs()) {
|
for (File classesDir : this.sourceSet.getOutput().getClassesDirs()) {
|
||||||
|
|
|
@ -26,6 +26,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.context.annotation.Conditional;
|
import org.springframework.context.annotation.Conditional;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that a class provides configuration that can be automatically applied by
|
* Indicates that a class provides configuration that can be automatically applied by
|
||||||
|
@ -33,6 +34,10 @@ import org.springframework.context.annotation.Configuration;
|
||||||
* {@link Configuration @Configuration} with the exception that
|
* {@link Configuration @Configuration} with the exception that
|
||||||
* {@literal Configuration#proxyBeanMethods() proxyBeanMethods} is always {@code false}.
|
* {@literal Configuration#proxyBeanMethods() proxyBeanMethods} is always {@code false}.
|
||||||
* <p>
|
* <p>
|
||||||
|
* They are located using the {@link AutoConfigurationLoader} and the
|
||||||
|
* {@link SpringFactoriesLoader} mechanism (keyed against
|
||||||
|
* {@link EnableAutoConfiguration}).
|
||||||
|
* <p>
|
||||||
* Generally auto-configuration classes are marked as {@link Conditional @Conditional}
|
* Generally auto-configuration classes are marked as {@link Conditional @Conditional}
|
||||||
* (most often using {@link ConditionalOnClass @ConditionalOnClass} and
|
* (most often using {@link ConditionalOnClass @ConditionalOnClass} and
|
||||||
* {@link ConditionalOnMissingBean @ConditionalOnMissingBean} annotations).
|
* {@link ConditionalOnMissingBean @ConditionalOnMissingBean} annotations).
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2019 the original author or authors.
|
* Copyright 2012-2022 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.
|
||||||
|
@ -17,6 +17,7 @@
|
||||||
package org.springframework.boot.autoconfigure;
|
package org.springframework.boot.autoconfigure;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||||
|
@ -54,13 +55,20 @@ public class AutoConfigurationExcludeFilter implements TypeFilter, BeanClassLoad
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isAutoConfiguration(MetadataReader metadataReader) {
|
private boolean isAutoConfiguration(MetadataReader metadataReader) {
|
||||||
return getAutoConfigurations().contains(metadataReader.getClassMetadata().getClassName());
|
boolean annotatedWithAutoConfiguration = metadataReader.getAnnotationMetadata()
|
||||||
|
.isAnnotated(AutoConfiguration.class.getName());
|
||||||
|
return annotatedWithAutoConfiguration
|
||||||
|
|| getAutoConfigurations().contains(metadataReader.getClassMetadata().getClassName());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<String> getAutoConfigurations() {
|
protected List<String> getAutoConfigurations() {
|
||||||
if (this.autoConfigurations == null) {
|
if (this.autoConfigurations == null) {
|
||||||
this.autoConfigurations = SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class,
|
List<String> autoConfigurations = new ArrayList<>();
|
||||||
this.beanClassLoader);
|
autoConfigurations.addAll(
|
||||||
|
SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class, this.beanClassLoader));
|
||||||
|
autoConfigurations
|
||||||
|
.addAll(new AutoConfigurationLoader().loadNames(AutoConfiguration.class, this.beanClassLoader));
|
||||||
|
this.autoConfigurations = autoConfigurations;
|
||||||
}
|
}
|
||||||
return this.autoConfigurations;
|
return this.autoConfigurations;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2020 the original author or authors.
|
* Copyright 2012-2022 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.util.StringUtils;
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
* @author Madhura Bhave
|
* @author Madhura Bhave
|
||||||
|
* @author Moritz Halbritter
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
* @see EnableAutoConfiguration
|
* @see EnableAutoConfiguration
|
||||||
*/
|
*/
|
||||||
|
@ -167,7 +168,9 @@ public class AutoConfigurationImportSelector implements DeferredImportSelector,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the auto-configuration class names that should be considered. By default
|
* Return the auto-configuration class names that should be considered. By default
|
||||||
* this method will load candidates using {@link SpringFactoriesLoader} with
|
* this method will load candidates using {@link AutoConfigurationLoader} with
|
||||||
|
* {@link #getSpringFactoriesLoaderFactoryClass()}. For backward compatible reasons it
|
||||||
|
* will also consider {@link SpringFactoriesLoader} with
|
||||||
* {@link #getSpringFactoriesLoaderFactoryClass()}.
|
* {@link #getSpringFactoriesLoaderFactoryClass()}.
|
||||||
* @param metadata the source metadata
|
* @param metadata the source metadata
|
||||||
* @param attributes the {@link #getAttributes(AnnotationMetadata) annotation
|
* @param attributes the {@link #getAttributes(AnnotationMetadata) annotation
|
||||||
|
@ -175,9 +178,12 @@ public class AutoConfigurationImportSelector implements DeferredImportSelector,
|
||||||
* @return a list of candidate configurations
|
* @return a list of candidate configurations
|
||||||
*/
|
*/
|
||||||
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
|
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
|
||||||
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
|
List<String> configurations = new ArrayList<>();
|
||||||
getBeanClassLoader());
|
configurations.addAll(
|
||||||
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
|
SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()));
|
||||||
|
configurations.addAll(new AutoConfigurationLoader().loadNames(AutoConfiguration.class, getBeanClassLoader()));
|
||||||
|
Assert.notEmpty(configurations,
|
||||||
|
"No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring-boot/org.springframework.boot.autoconfigure.AutoConfiguration. If you "
|
||||||
+ "are using a custom packaging, make sure that file is correct.");
|
+ "are using a custom packaging, make sure that file is correct.");
|
||||||
return configurations;
|
return configurations;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,113 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2022 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
|
||||||
|
*
|
||||||
|
* https://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.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.core.io.UrlResource;
|
||||||
|
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the names of annotated classes, usually @{@link AutoConfiguration}.
|
||||||
|
*
|
||||||
|
* The names of the classes are stored in files named META-INF/spring-boot/{full qualified
|
||||||
|
* name of the annotation}. Every line contains the full qualified class name of the
|
||||||
|
* annotated class. Comments are supported using the # character.
|
||||||
|
*
|
||||||
|
* @author Moritz Halbritter
|
||||||
|
* @see AutoConfiguration
|
||||||
|
* @see SpringFactoriesLoader
|
||||||
|
*/
|
||||||
|
class AutoConfigurationLoader {
|
||||||
|
|
||||||
|
private static final String LOCATION = "META-INF/spring-boot/";
|
||||||
|
|
||||||
|
private static final String COMMENT_START = "#";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the names of annotated classes.
|
||||||
|
* @param annotation annotation to load
|
||||||
|
* @param classLoader class loader to use for loading
|
||||||
|
* @return list of names of annotated classes
|
||||||
|
*/
|
||||||
|
List<String> loadNames(Class<?> annotation, ClassLoader classLoader) {
|
||||||
|
Assert.notNull(annotation, "'annotation' must not be null");
|
||||||
|
ClassLoader classLoaderToUse = decideClassloader(classLoader);
|
||||||
|
String location = LOCATION + annotation.getName();
|
||||||
|
Enumeration<URL> urls = findUrlsInClasspath(classLoaderToUse, location);
|
||||||
|
List<String> autoConfigurations = new ArrayList<>();
|
||||||
|
while (urls.hasMoreElements()) {
|
||||||
|
URL url = urls.nextElement();
|
||||||
|
autoConfigurations.addAll(readAutoConfigurations(url));
|
||||||
|
}
|
||||||
|
return autoConfigurations;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ClassLoader decideClassloader(ClassLoader classLoader) {
|
||||||
|
if (classLoader == null) {
|
||||||
|
return AutoConfigurationLoader.class.getClassLoader();
|
||||||
|
}
|
||||||
|
return classLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Enumeration<URL> findUrlsInClasspath(ClassLoader classLoader, String location) {
|
||||||
|
try {
|
||||||
|
return classLoader.getResources(location);
|
||||||
|
}
|
||||||
|
catch (IOException ex) {
|
||||||
|
throw new IllegalArgumentException("Failed to load autoconfigurations from location [" + location + "]",
|
||||||
|
ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> readAutoConfigurations(URL url) {
|
||||||
|
try (BufferedReader reader = new BufferedReader(
|
||||||
|
new InputStreamReader(new UrlResource(url).getInputStream(), StandardCharsets.UTF_8))) {
|
||||||
|
List<String> autoConfigurations = new ArrayList<>();
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
line = stripComment(line);
|
||||||
|
line = line.trim();
|
||||||
|
if (line.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
autoConfigurations.add(line);
|
||||||
|
}
|
||||||
|
return autoConfigurations;
|
||||||
|
}
|
||||||
|
catch (IOException ex) {
|
||||||
|
throw new IllegalArgumentException("Unable to load autoconfigurations from location [" + url + "]", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String stripComment(String line) {
|
||||||
|
int commentStart = line.indexOf(COMMENT_START);
|
||||||
|
if (commentStart == -1) {
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
return line.substring(0, commentStart);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2020 the original author or authors.
|
* Copyright 2012-2022 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.
|
||||||
|
@ -60,9 +60,9 @@ import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||||
* and classes can be searched.
|
* and classes can be searched.
|
||||||
* <p>
|
* <p>
|
||||||
* Auto-configuration classes are regular Spring {@link Configuration @Configuration}
|
* Auto-configuration classes are regular Spring {@link Configuration @Configuration}
|
||||||
* beans. They are located using the {@link SpringFactoriesLoader} mechanism (keyed
|
* beans. They are located using the {@link AutoConfigurationLoader} and the
|
||||||
* against this class). Generally auto-configuration beans are
|
* {@link SpringFactoriesLoader} mechanism (keyed against this class). Generally
|
||||||
* {@link Conditional @Conditional} beans (most often using
|
* auto-configuration beans are {@link Conditional @Conditional} beans (most often using
|
||||||
* {@link ConditionalOnClass @ConditionalOnClass} and
|
* {@link ConditionalOnClass @ConditionalOnClass} and
|
||||||
* {@link ConditionalOnMissingBean @ConditionalOnMissingBean} annotations).
|
* {@link ConditionalOnMissingBean @ConditionalOnMissingBean} annotations).
|
||||||
*
|
*
|
||||||
|
|
|
@ -44,6 +44,7 @@ import org.springframework.util.ObjectUtils;
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
|
* @author Moritz Halbritter
|
||||||
*/
|
*/
|
||||||
class ImportAutoConfigurationImportSelector extends AutoConfigurationImportSelector implements DeterminableImports {
|
class ImportAutoConfigurationImportSelector extends AutoConfigurationImportSelector implements DeterminableImports {
|
||||||
|
|
||||||
|
@ -94,7 +95,10 @@ class ImportAutoConfigurationImportSelector extends AutoConfigurationImportSelec
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Collection<String> loadFactoryNames(Class<?> source) {
|
protected Collection<String> loadFactoryNames(Class<?> source) {
|
||||||
return SpringFactoriesLoader.loadFactoryNames(source, getBeanClassLoader());
|
List<String> factoryNames = new ArrayList<>();
|
||||||
|
factoryNames.addAll(SpringFactoriesLoader.loadFactoryNames(source, getBeanClassLoader()));
|
||||||
|
factoryNames.addAll(new AutoConfigurationLoader().loadNames(source, getBeanClassLoader()));
|
||||||
|
return factoryNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2022 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
|
||||||
|
*
|
||||||
|
* https://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.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
class AutoConfigurationLoaderTests {
|
||||||
|
|
||||||
|
private AutoConfigurationLoader sut;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
this.sut = new AutoConfigurationLoader();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void loadNames() {
|
||||||
|
List<String> classNames = this.sut.loadNames(TestAutoConfiguration.class, null);
|
||||||
|
|
||||||
|
assertThat(classNames).containsExactly("class1", "class2", "class3");
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoConfiguration
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface TestAutoConfiguration {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
# A comment spanning a complete line
|
||||||
|
class1
|
||||||
|
|
||||||
|
class2 # with comment at the end
|
||||||
|
# Comment with some whitespace in front
|
||||||
|
class3
|
|
@ -24,16 +24,18 @@ You can browse the source code of {spring-boot-autoconfigure-module-code}[`sprin
|
||||||
|
|
||||||
[[features.developing-auto-configuration.locating-auto-configuration-candidates]]
|
[[features.developing-auto-configuration.locating-auto-configuration-candidates]]
|
||||||
=== Locating Auto-configuration Candidates
|
=== Locating Auto-configuration Candidates
|
||||||
Spring Boot checks for the presence of a `META-INF/spring.factories` file within your published jar.
|
|
||||||
The file should list your configuration classes under the `EnableAutoConfiguration` key, as shown in the following example:
|
Spring Boot checks for the presence of a `META-INF/spring-boot/org.springframework.boot.autoconfigure.AutoConfiguration` file within your published jar.
|
||||||
|
The file should list your configuration classes, as shown in the following example:
|
||||||
|
|
||||||
[indent=0]
|
[indent=0]
|
||||||
----
|
----
|
||||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
com.mycorp.libx.autoconfigure.LibXAutoConfiguration
|
||||||
com.mycorp.libx.autoconfigure.LibXAutoConfiguration,\
|
|
||||||
com.mycorp.libx.autoconfigure.LibXWebAutoConfiguration
|
com.mycorp.libx.autoconfigure.LibXWebAutoConfiguration
|
||||||
----
|
----
|
||||||
|
|
||||||
|
TIP: You can use comments via `#` in this file.
|
||||||
|
|
||||||
NOTE: Auto-configurations must be loaded that way _only_.
|
NOTE: Auto-configurations must be loaded that way _only_.
|
||||||
Make sure that they are defined in a specific package space and that they are never the target of component scanning.
|
Make sure that they are defined in a specific package space and that they are never the target of component scanning.
|
||||||
Furthermore, auto-configuration classes should not enable component scanning to find additional components.
|
Furthermore, auto-configuration classes should not enable component scanning to find additional components.
|
||||||
|
|
|
@ -716,13 +716,18 @@ include::code:MyJdbcTests[]
|
||||||
|
|
||||||
NOTE: Make sure to not use the regular `@Import` annotation to import auto-configurations as they are handled in a specific way by Spring Boot.
|
NOTE: Make sure to not use the regular `@Import` annotation to import auto-configurations as they are handled in a specific way by Spring Boot.
|
||||||
|
|
||||||
Alternatively, additional auto-configurations can be added for any use of a slice annotation by registering them in `META-INF/spring.factories` as shown in the following example:
|
Alternatively, additional auto-configurations can be added for any use of a slice annotation by registering them in a file stored in `META-INF/spring-boot` as shown in the following example:
|
||||||
|
|
||||||
|
.META-INF/spring-boot/org.springframework.boot.test.autoconfigure.jdbc.JdbcTest
|
||||||
[indent=0]
|
[indent=0]
|
||||||
----
|
----
|
||||||
org.springframework.boot.test.autoconfigure.jdbc.JdbcTest=com.example.IntegrationAutoConfiguration
|
com.example.IntegrationAutoConfiguration
|
||||||
----
|
----
|
||||||
|
|
||||||
|
In this example, the `com.example.IntegrationAutoConfiguration` is enabled on every test annotated with `@JdbcTest`.
|
||||||
|
|
||||||
|
TIP: You can use comments via `#` in this file.
|
||||||
|
|
||||||
TIP: A slice or `@AutoConfigure...` annotation can be customized this way as long as it is meta-annotated with `@ImportAutoConfiguration`.
|
TIP: A slice or `@AutoConfigure...` annotation can be customized this way as long as it is meta-annotated with `@ImportAutoConfiguration`.
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue