Skip to content

Commit d42f675

Browse files
committed
Merge branch '2.7.x'
2 parents 3b22888 + d7b229d commit d42f675

File tree

45 files changed

+84
-68
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+84
-68
lines changed

Diff for: buildSrc/src/main/java/org/springframework/boot/build/autoconfigure/AutoConfigurationMetadata.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public AutoConfigurationMetadata() {
6666
.withPathSensitivity(PathSensitivity.RELATIVE).withPropertyName("spring.factories");
6767
getInputs()
6868
.file((Callable<File>) () -> new File(this.sourceSet.getOutput().getResourcesDir(),
69-
"META-INF/spring-boot/org.springframework.boot.autoconfigure.AutoConfiguration"))
69+
"META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports"))
7070
.withPathSensitivity(PathSensitivity.RELATIVE)
7171
.withPropertyName("org.springframework.boot.autoconfigure.AutoConfiguration");
7272

@@ -137,17 +137,17 @@ private Set<String> readSpringFactories() throws IOException {
137137

138138
/**
139139
* Reads auto-configurations from
140-
* META-INF/spring-boot/org.springframework.boot.autoconfigure.AutoConfiguration.
140+
* META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports.
141141
* @return auto-configurations
142142
*/
143143
private List<String> readAutoConfigurationsFile() throws IOException {
144144
File file = new File(this.sourceSet.getOutput().getResourcesDir(),
145-
"META-INF/spring-boot/org.springframework.boot.autoconfigure.AutoConfiguration");
145+
"META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports");
146146
if (!file.exists()) {
147147
return Collections.emptyList();
148148
}
149149
// Nearly identical copy of
150-
// org.springframework.boot.autoconfigure.AutoConfigurationLoader.readAutoConfigurations
150+
// org.springframework.boot.context.annotation.ImportCandidates.load
151151
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)))) {
152152
List<String> autoConfigurations = new ArrayList<>();
153153
String line;

Diff for: buildSrc/src/main/java/org/springframework/boot/build/test/autoconfigure/TestSliceMetadata.java

+6-3
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ private Properties readTestSlices() throws IOException {
106106
Properties springFactories = readSpringFactories(
107107
new File(this.sourceSet.getOutput().getResourcesDir(), "META-INF/spring.factories"));
108108
readTestSlicesDirectory(springFactories,
109-
new File(this.sourceSet.getOutput().getResourcesDir(), "META-INF/spring-boot/"));
109+
new File(this.sourceSet.getOutput().getResourcesDir(), "META-INF/spring/"));
110110
for (File classesDir : this.sourceSet.getOutput().getClassesDirs()) {
111111
addTestSlices(testSlices, classesDir, metadataReaderFactory, springFactories);
112112
}
@@ -123,14 +123,17 @@ private Properties readTestSlices() throws IOException {
123123
* @param directory directory to scan
124124
*/
125125
private void readTestSlicesDirectory(Properties springFactories, File directory) {
126-
File[] files = directory.listFiles();
126+
File[] files = directory.listFiles((dir, name) -> name.endsWith(".imports"));
127127
if (files == null) {
128128
return;
129129
}
130130
for (File file : files) {
131131
try {
132132
List<String> lines = removeComments(Files.readAllLines(file.toPath()));
133-
springFactories.setProperty(file.getName(), StringUtils.collectionToCommaDelimitedString(lines));
133+
String fileNameWithoutExtension = file.getName().substring(0,
134+
file.getName().length() - ".imports".length());
135+
springFactories.setProperty(fileNameWithoutExtension,
136+
StringUtils.collectionToCommaDelimitedString(lines));
134137
}
135138
catch (IOException ex) {
136139
throw new UncheckedIOException("Failed to read file " + file, ex);

Diff for: spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfiguration.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
2626
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
27+
import org.springframework.boot.context.annotation.ImportCandidates;
2728
import org.springframework.context.annotation.Conditional;
2829
import org.springframework.context.annotation.Configuration;
2930
import org.springframework.core.io.support.SpringFactoriesLoader;
@@ -34,9 +35,8 @@
3435
* {@link Configuration @Configuration} with the exception that
3536
* {@literal Configuration#proxyBeanMethods() proxyBeanMethods} is always {@code false}.
3637
* <p>
37-
* They are located using the {@link AutoConfigurationLoader} and the
38-
* {@link SpringFactoriesLoader} mechanism (keyed against
39-
* {@link EnableAutoConfiguration}).
38+
* They are located using {@link ImportCandidates} and the {@link SpringFactoriesLoader}
39+
* mechanism (keyed against {@link EnableAutoConfiguration}).
4040
* <p>
4141
* Generally auto-configuration classes are marked as {@link Conditional @Conditional}
4242
* (most often using {@link ConditionalOnClass @ConditionalOnClass} and

Diff for: spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationExcludeFilter.java

+3-4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.List;
2222

2323
import org.springframework.beans.factory.BeanClassLoaderAware;
24+
import org.springframework.boot.context.annotation.ImportCandidates;
2425
import org.springframework.context.annotation.Configuration;
2526
import org.springframework.core.io.support.SpringFactoriesLoader;
2627
import org.springframework.core.type.classreading.MetadataReader;
@@ -63,11 +64,9 @@ private boolean isAutoConfiguration(MetadataReader metadataReader) {
6364

6465
protected List<String> getAutoConfigurations() {
6566
if (this.autoConfigurations == null) {
66-
List<String> autoConfigurations = new ArrayList<>();
67-
autoConfigurations.addAll(
67+
List<String> autoConfigurations = new ArrayList<>(
6868
SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class, this.beanClassLoader));
69-
autoConfigurations
70-
.addAll(new AutoConfigurationLoader().loadNames(AutoConfiguration.class, this.beanClassLoader));
69+
ImportCandidates.load(AutoConfiguration.class, this.beanClassLoader).forEach(autoConfigurations::add);
7170
this.autoConfigurations = autoConfigurations;
7271
}
7372
return this.autoConfigurations;

Diff for: spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationImportSelector.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import org.springframework.beans.factory.BeanFactoryAware;
4141
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
4242
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
43+
import org.springframework.boot.context.annotation.ImportCandidates;
4344
import org.springframework.boot.context.properties.bind.Binder;
4445
import org.springframework.context.EnvironmentAware;
4546
import org.springframework.context.ResourceLoaderAware;
@@ -168,7 +169,7 @@ protected Class<?> getAnnotationClass() {
168169

169170
/**
170171
* Return the auto-configuration class names that should be considered. By default
171-
* this method will load candidates using {@link AutoConfigurationLoader} with
172+
* this method will load candidates using {@link ImportCandidates} with
172173
* {@link #getSpringFactoriesLoaderFactoryClass()}. For backward compatible reasons it
173174
* will also consider {@link SpringFactoriesLoader} with
174175
* {@link #getSpringFactoriesLoaderFactoryClass()}.
@@ -178,12 +179,11 @@ protected Class<?> getAnnotationClass() {
178179
* @return a list of candidate configurations
179180
*/
180181
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
181-
List<String> configurations = new ArrayList<>();
182-
configurations.addAll(
182+
List<String> configurations = new ArrayList<>(
183183
SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()));
184-
configurations.addAll(new AutoConfigurationLoader().loadNames(AutoConfiguration.class, getBeanClassLoader()));
184+
ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()).forEach(configurations::add);
185185
Assert.notEmpty(configurations,
186-
"No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring-boot/org.springframework.boot.autoconfigure.AutoConfiguration. If you "
186+
"No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you "
187187
+ "are using a custom packaging, make sure that file is correct.");
188188
return configurations;
189189
}

Diff for: spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/EnableAutoConfiguration.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
2727
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
2828
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
29+
import org.springframework.boot.context.annotation.ImportCandidates;
2930
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
3031
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
3132
import org.springframework.context.annotation.Conditional;
@@ -60,7 +61,7 @@
6061
* and classes can be searched.
6162
* <p>
6263
* Auto-configuration classes are regular Spring {@link Configuration @Configuration}
63-
* beans. They are located using the {@link AutoConfigurationLoader} and the
64+
* beans. They are located using {@link ImportCandidates} and the
6465
* {@link SpringFactoriesLoader} mechanism (keyed against this class). Generally
6566
* auto-configuration beans are {@link Conditional @Conditional} beans (most often using
6667
* {@link ConditionalOnClass @ConditionalOnClass} and

Diff for: spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ImportAutoConfiguration.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@
5959

6060
/**
6161
* The auto-configuration classes that should be imported. When empty, the classes are
62-
* specified using a file in {@code META-INF/spring-boot} where the file name is the
63-
* fully-qualified name of the annotated class.
62+
* specified using a file in {@code META-INF/spring} where the file name is the
63+
* fully-qualified name of the annotated class, suffixed with '.imports'.
6464
* @return the classes to import
6565
*/
6666
@AliasFor("value")

Diff for: spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ImportAutoConfigurationImportSelector.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2021 the original author or authors.
2+
* Copyright 2012-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -28,6 +28,7 @@
2828
import java.util.Set;
2929

3030
import org.springframework.boot.context.annotation.DeterminableImports;
31+
import org.springframework.boot.context.annotation.ImportCandidates;
3132
import org.springframework.core.annotation.AnnotatedElementUtils;
3233
import org.springframework.core.annotation.AnnotationAttributes;
3334
import org.springframework.core.annotation.AnnotationUtils;
@@ -95,9 +96,9 @@ private Collection<String> getConfigurationsForAnnotation(Class<?> source, Annot
9596
}
9697

9798
protected Collection<String> loadFactoryNames(Class<?> source) {
98-
List<String> factoryNames = new ArrayList<>();
99-
factoryNames.addAll(SpringFactoriesLoader.loadFactoryNames(source, getBeanClassLoader()));
100-
factoryNames.addAll(new AutoConfigurationLoader().loadNames(source, getBeanClassLoader()));
99+
List<String> factoryNames = new ArrayList<>(
100+
SpringFactoriesLoader.loadFactoryNames(source, getBeanClassLoader()));
101+
ImportCandidates.load(source, getBeanClassLoader()).forEach(factoryNames::add);
101102
return factoryNames;
102103
}
103104

Diff for: spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/AutoConfigurationImportSelectorTests.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration;
3333
import org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration;
3434
import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration;
35+
import org.springframework.boot.context.annotation.ImportCandidates;
3536
import org.springframework.context.annotation.Configuration;
3637
import org.springframework.core.io.DefaultResourceLoader;
3738
import org.springframework.core.type.AnnotationMetadata;
@@ -212,7 +213,10 @@ private String[] selectImports(Class<?> source) {
212213
}
213214

214215
private List<String> getAutoConfigurationClassNames() {
215-
return new AutoConfigurationLoader().loadNames(AutoConfiguration.class, getClass().getClassLoader());
216+
List<String> autoConfigurationClassNames = new ArrayList<>();
217+
ImportCandidates.load(AutoConfiguration.class, getClass().getClassLoader())
218+
.forEach(autoConfigurationClassNames::add);
219+
return autoConfigurationClassNames;
216220
}
217221

218222
private class TestAutoConfigurationImportSelector extends AutoConfigurationImportSelector {

Diff for: spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/developing-auto-configuration.adoc

+2-2

Diff for: spring-boot-project/spring-boot-docs/src/docs/asciidoc/features/testing.adoc

+2-2
+38-19
Original file line numberDiff line numberDiff line change
@@ -14,65 +14,84 @@
1414
* limitations under the License.
1515
*/
1616

17-
package org.springframework.boot.autoconfigure;
17+
package org.springframework.boot.context.annotation;
1818

1919
import java.io.BufferedReader;
2020
import java.io.IOException;
2121
import java.io.InputStreamReader;
2222
import java.net.URL;
2323
import java.nio.charset.StandardCharsets;
2424
import java.util.ArrayList;
25+
import java.util.Collections;
2526
import java.util.Enumeration;
27+
import java.util.Iterator;
2628
import java.util.List;
2729

30+
import org.jetbrains.annotations.NotNull;
31+
2832
import org.springframework.core.io.UrlResource;
29-
import org.springframework.core.io.support.SpringFactoriesLoader;
3033
import org.springframework.util.Assert;
3134

3235
/**
33-
* Loads the names of annotated classes, usually @{@link AutoConfiguration}.
36+
* Contains import candidates, usually auto-configurations.
3437
*
35-
* The names of the classes are stored in files named META-INF/spring-boot/{full qualified
36-
* name of the annotation}. Every line contains the full qualified class name of the
37-
* annotated class. Comments are supported using the # character.
38+
* The {@link #load(Class, ClassLoader)} method can be used to discover the import
39+
* candidates.
3840
*
3941
* @author Moritz Halbritter
40-
* @see AutoConfiguration
41-
* @see SpringFactoriesLoader
42+
* @since 2.7.0
4243
*/
43-
class AutoConfigurationLoader {
44+
public final class ImportCandidates implements Iterable<String> {
4445

45-
private static final String LOCATION = "META-INF/spring-boot/";
46+
private static final String LOCATION = "META-INF/spring/%s.imports";
4647

4748
private static final String COMMENT_START = "#";
4849

50+
private final List<String> candidates;
51+
52+
private ImportCandidates(List<String> candidates) {
53+
Assert.notNull(candidates, "'candidates' must not be null");
54+
this.candidates = Collections.unmodifiableList(candidates);
55+
}
56+
57+
@NotNull
58+
@Override
59+
public Iterator<String> iterator() {
60+
return this.candidates.iterator();
61+
}
62+
4963
/**
50-
* Loads the names of annotated classes.
64+
* Loads the names of import candidates from the classpath.
65+
*
66+
* The names of the import candidates are stored in files named
67+
* {@code META-INF/spring/full-qualified-annotation-name.import} on the classpath.
68+
* Every line contains the full qualified name of the candidate class. Comments are
69+
* supported using the # character.
5170
* @param annotation annotation to load
5271
* @param classLoader class loader to use for loading
5372
* @return list of names of annotated classes
5473
*/
55-
List<String> loadNames(Class<?> annotation, ClassLoader classLoader) {
74+
public static ImportCandidates load(Class<?> annotation, ClassLoader classLoader) {
5675
Assert.notNull(annotation, "'annotation' must not be null");
5776
ClassLoader classLoaderToUse = decideClassloader(classLoader);
58-
String location = LOCATION + annotation.getName();
77+
String location = String.format(LOCATION, annotation.getName());
5978
Enumeration<URL> urls = findUrlsInClasspath(classLoaderToUse, location);
6079
List<String> autoConfigurations = new ArrayList<>();
6180
while (urls.hasMoreElements()) {
6281
URL url = urls.nextElement();
6382
autoConfigurations.addAll(readAutoConfigurations(url));
6483
}
65-
return autoConfigurations;
84+
return new ImportCandidates(autoConfigurations);
6685
}
6786

68-
private ClassLoader decideClassloader(ClassLoader classLoader) {
87+
private static ClassLoader decideClassloader(ClassLoader classLoader) {
6988
if (classLoader == null) {
70-
return AutoConfigurationLoader.class.getClassLoader();
89+
return ImportCandidates.class.getClassLoader();
7190
}
7291
return classLoader;
7392
}
7493

75-
private Enumeration<URL> findUrlsInClasspath(ClassLoader classLoader, String location) {
94+
private static Enumeration<URL> findUrlsInClasspath(ClassLoader classLoader, String location) {
7695
try {
7796
return classLoader.getResources(location);
7897
}
@@ -82,7 +101,7 @@ private Enumeration<URL> findUrlsInClasspath(ClassLoader classLoader, String loc
82101
}
83102
}
84103

85-
private List<String> readAutoConfigurations(URL url) {
104+
private static List<String> readAutoConfigurations(URL url) {
86105
try (BufferedReader reader = new BufferedReader(
87106
new InputStreamReader(new UrlResource(url).getInputStream(), StandardCharsets.UTF_8))) {
88107
List<String> autoConfigurations = new ArrayList<>();
@@ -102,7 +121,7 @@ private List<String> readAutoConfigurations(URL url) {
102121
}
103122
}
104123

105-
private String stripComment(String line) {
124+
private static String stripComment(String line) {
106125
int commentStart = line.indexOf(COMMENT_START);
107126
if (commentStart == -1) {
108127
return line;
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ class1
33

44
class2 # with comment at the end
55
# Comment with some whitespace in front
6-
class3
6+
class3

0 commit comments

Comments
 (0)