diff --git a/buildSrc/src/main/java/org/springframework/boot/build/autoconfigure/AutoConfigurationMetadata.java b/buildSrc/src/main/java/org/springframework/boot/build/autoconfigure/AutoConfigurationMetadata.java index 636a24396da..535be934a70 100644 --- a/buildSrc/src/main/java/org/springframework/boot/build/autoconfigure/AutoConfigurationMetadata.java +++ b/buildSrc/src/main/java/org/springframework/boot/build/autoconfigure/AutoConfigurationMetadata.java @@ -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"); * you may not use this file except in compliance with the License. @@ -16,14 +16,19 @@ package org.springframework.boot.build.autoconfigure; +import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.io.Reader; +import java.util.ArrayList; +import java.util.Collections; import java.util.LinkedHashSet; +import java.util.List; import java.util.Properties; import java.util.Set; import java.util.concurrent.Callable; @@ -48,6 +53,8 @@ import org.springframework.util.StringUtils; */ public class AutoConfigurationMetadata extends DefaultTask { + private static final String COMMENT_START = "#"; + private SourceSet sourceSet; private File outputFile; @@ -57,6 +64,12 @@ public class AutoConfigurationMetadata extends DefaultTask { .file((Callable) () -> new File(this.sourceSet.getOutput().getResourcesDir(), "META-INF/spring.factories")) .withPathSensitivity(PathSensitivity.RELATIVE).withPropertyName("spring.factories"); + getInputs() + .file((Callable) () -> 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) () -> this.sourceSet.getProcessResourcesTaskName()); getProject().getConfigurations() .maybeCreate(AutoConfigurationPlugin.AUTO_CONFIGURATION_METADATA_CONFIGURATION_NAME); @@ -86,11 +99,9 @@ public class AutoConfigurationMetadata extends DefaultTask { private Properties readAutoConfiguration() throws IOException { Properties autoConfiguration = CollectionFactory.createSortedProperties(true); - Properties springFactories = readSpringFactories( - new File(this.sourceSet.getOutput().getResourcesDir(), "META-INF/spring.factories")); - String enableAutoConfiguration = springFactories - .getProperty("org.springframework.boot.autoconfigure.EnableAutoConfiguration"); - Set classNames = StringUtils.commaDelimitedListToSet(enableAutoConfiguration); + Set classNames = new LinkedHashSet<>(); + classNames.addAll(readSpringFactories()); + classNames.addAll(readAutoConfigurationsFile()); Set publicClassNames = new LinkedHashSet<>(); for (String className : classNames) { File classFile = findClassFile(className); @@ -109,6 +120,57 @@ public class AutoConfigurationMetadata extends DefaultTask { return autoConfiguration; } + /** + * Reads auto-configurations from META-INF/spring.factories. + * @return auto-configurations + */ + private Set 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 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 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) { String classFileName = className.replace(".", "/") + ".class"; for (File classesDir : this.sourceSet.getOutput().getClassesDirs()) { diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring-boot/org.springframework.boot.autoconfigure.AutoConfiguration b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring-boot/org.springframework.boot.autoconfigure.AutoConfiguration new file mode 100644 index 00000000000..e69de29bb2d diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfiguration.java index c3d79a43b1a..8ac17a19a00 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfiguration.java @@ -26,6 +26,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Conditional; 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 @@ -33,6 +34,10 @@ import org.springframework.context.annotation.Configuration; * {@link Configuration @Configuration} with the exception that * {@literal Configuration#proxyBeanMethods() proxyBeanMethods} is always {@code false}. *

+ * They are located using the {@link AutoConfigurationLoader} and the + * {@link SpringFactoriesLoader} mechanism (keyed against + * {@link EnableAutoConfiguration}). + *

* Generally auto-configuration classes are marked as {@link Conditional @Conditional} * (most often using {@link ConditionalOnClass @ConditionalOnClass} and * {@link ConditionalOnMissingBean @ConditionalOnMissingBean} annotations). diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationExcludeFilter.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationExcludeFilter.java index dc83e8b28e4..478653b0d65 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationExcludeFilter.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationExcludeFilter.java @@ -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"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ package org.springframework.boot.autoconfigure; import java.io.IOException; +import java.util.ArrayList; import java.util.List; import org.springframework.beans.factory.BeanClassLoaderAware; @@ -54,13 +55,20 @@ public class AutoConfigurationExcludeFilter implements TypeFilter, BeanClassLoad } 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 getAutoConfigurations() { if (this.autoConfigurations == null) { - this.autoConfigurations = SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class, - this.beanClassLoader); + List autoConfigurations = new ArrayList<>(); + autoConfigurations.addAll( + SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class, this.beanClassLoader)); + autoConfigurations + .addAll(new AutoConfigurationLoader().loadNames(AutoConfiguration.class, this.beanClassLoader)); + this.autoConfigurations = autoConfigurations; } return this.autoConfigurations; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java index d0e0b2bd8c5..8490bcef77b 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java @@ -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"); * 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 Stephane Nicoll * @author Madhura Bhave + * @author Moritz Halbritter * @since 1.3.0 * @see EnableAutoConfiguration */ @@ -167,7 +168,9 @@ public class AutoConfigurationImportSelector implements DeferredImportSelector, /** * 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()}. * @param metadata the source metadata * @param attributes the {@link #getAttributes(AnnotationMetadata) annotation @@ -175,10 +178,13 @@ public class AutoConfigurationImportSelector implements DeferredImportSelector, * @return a list of candidate configurations */ protected List getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { - List 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."); + List configurations = new ArrayList<>(); + configurations.addAll( + 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."); return configurations; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationLoader.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationLoader.java new file mode 100644 index 00000000000..5f8dc2b8290 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationLoader.java @@ -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 loadNames(Class annotation, ClassLoader classLoader) { + Assert.notNull(annotation, "'annotation' must not be null"); + ClassLoader classLoaderToUse = decideClassloader(classLoader); + String location = LOCATION + annotation.getName(); + Enumeration urls = findUrlsInClasspath(classLoaderToUse, location); + List 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 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 readAutoConfigurations(URL url) { + try (BufferedReader reader = new BufferedReader( + new InputStreamReader(new UrlResource(url).getInputStream(), StandardCharsets.UTF_8))) { + List 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); + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/EnableAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/EnableAutoConfiguration.java index eea76a0a4d5..624d9f3e9e4 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/EnableAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/EnableAutoConfiguration.java @@ -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"); * 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. *

* Auto-configuration classes are regular Spring {@link Configuration @Configuration} - * beans. They are located using the {@link SpringFactoriesLoader} mechanism (keyed - * against this class). Generally auto-configuration beans are - * {@link Conditional @Conditional} beans (most often using + * beans. They are located using the {@link AutoConfigurationLoader} and the + * {@link SpringFactoriesLoader} mechanism (keyed against this class). Generally + * auto-configuration beans are {@link Conditional @Conditional} beans (most often using * {@link ConditionalOnClass @ConditionalOnClass} and * {@link ConditionalOnMissingBean @ConditionalOnMissingBean} annotations). * diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ImportAutoConfigurationImportSelector.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ImportAutoConfigurationImportSelector.java index bfbae2a7503..0b2c5008853 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ImportAutoConfigurationImportSelector.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ImportAutoConfigurationImportSelector.java @@ -44,6 +44,7 @@ import org.springframework.util.ObjectUtils; * * @author Phillip Webb * @author Andy Wilkinson + * @author Moritz Halbritter */ class ImportAutoConfigurationImportSelector extends AutoConfigurationImportSelector implements DeterminableImports { @@ -94,7 +95,10 @@ class ImportAutoConfigurationImportSelector extends AutoConfigurationImportSelec } protected Collection loadFactoryNames(Class source) { - return SpringFactoriesLoader.loadFactoryNames(source, getBeanClassLoader()); + List factoryNames = new ArrayList<>(); + factoryNames.addAll(SpringFactoriesLoader.loadFactoryNames(source, getBeanClassLoader())); + factoryNames.addAll(new AutoConfigurationLoader().loadNames(source, getBeanClassLoader())); + return factoryNames; } @Override diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring-boot/org.springframework.boot.autoconfigure.AutoConfiguration b/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring-boot/org.springframework.boot.autoconfigure.AutoConfiguration new file mode 100644 index 00000000000..e69de29bb2d diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/AutoConfigurationLoaderTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/AutoConfigurationLoaderTests.java new file mode 100644 index 00000000000..ef63167386d --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/AutoConfigurationLoaderTests.java @@ -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 classNames = this.sut.loadNames(TestAutoConfiguration.class, null); + + assertThat(classNames).containsExactly("class1", "class2", "class3"); + } + + @AutoConfiguration + @Target(ElementType.TYPE) + @Retention(RetentionPolicy.RUNTIME) + public @interface TestAutoConfiguration { + + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/resources/META-INF/spring-boot/org.springframework.boot.autoconfigure.AutoConfigurationLoaderTests$TestAutoConfiguration b/spring-boot-project/spring-boot-autoconfigure/src/test/resources/META-INF/spring-boot/org.springframework.boot.autoconfigure.AutoConfigurationLoaderTests$TestAutoConfiguration new file mode 100644 index 00000000000..d42712a8c2b --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/resources/META-INF/spring-boot/org.springframework.boot.autoconfigure.AutoConfigurationLoaderTests$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 \ No newline at end of file diff --git a/spring-boot-project/spring-boot-devtools/src/main/resources/META-INF/spring-boot/org.springframework.boot.autoconfigure.AutoConfiguration b/spring-boot-project/spring-boot-devtools/src/main/resources/META-INF/spring-boot/org.springframework.boot.autoconfigure.AutoConfiguration new file mode 100644 index 00000000000..e69de29bb2d diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/developing-auto-configuration.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/developing-auto-configuration.adoc index b6c52e41404..d009c2b3c61 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/developing-auto-configuration.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/developing-auto-configuration.adoc @@ -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]] === 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] ---- - org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - com.mycorp.libx.autoconfigure.LibXAutoConfiguration,\ - com.mycorp.libx.autoconfigure.LibXWebAutoConfiguration + com.mycorp.libx.autoconfigure.LibXAutoConfiguration + com.mycorp.libx.autoconfigure.LibXWebAutoConfiguration ---- +TIP: You can use comments via `#` in this file. + 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. Furthermore, auto-configuration classes should not enable component scanning to find additional components. diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc index 16b67977054..a80a50a027b 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc @@ -769,13 +769,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. -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] ---- - 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`. diff --git a/spring-boot-project/spring-boot-test-autoconfigure/src/main/resources/META-INF/spring-boot/org.springframework.boot.autoconfigure.AutoConfiguration b/spring-boot-project/spring-boot-test-autoconfigure/src/main/resources/META-INF/spring-boot/org.springframework.boot.autoconfigure.AutoConfiguration new file mode 100644 index 00000000000..e69de29bb2d diff --git a/spring-boot-system-tests/spring-boot-deployment-tests/src/main/resources/META-INF/spring-boot/org.springframework.boot.autoconfigure.AutoConfiguration b/spring-boot-system-tests/spring-boot-deployment-tests/src/main/resources/META-INF/spring-boot/org.springframework.boot.autoconfigure.AutoConfiguration new file mode 100644 index 00000000000..e69de29bb2d diff --git a/spring-boot-tests/spring-boot-integration-tests/spring-boot-server-tests/spring-boot-server-tests-app/src/main/resources/META-INF/spring-boot/org.springframework.boot.autoconfigure.AutoConfiguration b/spring-boot-tests/spring-boot-integration-tests/spring-boot-server-tests/spring-boot-server-tests-app/src/main/resources/META-INF/spring-boot/org.springframework.boot.autoconfigure.AutoConfiguration new file mode 100644 index 00000000000..e69de29bb2d