Skip to content

Commit 08022ba

Browse files
Remove support for locating imports using spring.factories
With this commit, loading `@AutoConfiguration`, `@ImportAutoConfiguration`, and `@ManagementContextConfiguration` classes is supported with `.imports` files only. Support for loading these classes with `spring.factories` is removed. Closes gh-29699
1 parent 6b8575b commit 08022ba

File tree

9 files changed

+35
-100
lines changed

9 files changed

+35
-100
lines changed

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

Lines changed: 8 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,13 @@
2323
import java.io.FileWriter;
2424
import java.io.IOException;
2525
import java.io.InputStream;
26-
import java.io.InputStreamReader;
27-
import java.io.Reader;
28-
import java.util.ArrayList;
2926
import java.util.Collections;
3027
import java.util.LinkedHashSet;
3128
import java.util.List;
3229
import java.util.Properties;
3330
import java.util.Set;
3431
import java.util.concurrent.Callable;
32+
import java.util.stream.Collectors;
3533

3634
import org.gradle.api.DefaultTask;
3735
import org.gradle.api.Task;
@@ -43,13 +41,13 @@
4341
import org.springframework.asm.ClassReader;
4442
import org.springframework.asm.Opcodes;
4543
import org.springframework.core.CollectionFactory;
46-
import org.springframework.util.StringUtils;
4744

4845
/**
4946
* A {@link Task} for generating metadata describing a project's auto-configuration
5047
* classes.
5148
*
5249
* @author Andy Wilkinson
50+
* @author Scott Frederick
5351
*/
5452
public class AutoConfigurationMetadata extends DefaultTask {
5553

@@ -60,10 +58,6 @@ public class AutoConfigurationMetadata extends DefaultTask {
6058
private File outputFile;
6159

6260
public AutoConfigurationMetadata() {
63-
getInputs()
64-
.file((Callable<File>) () -> new File(this.sourceSet.getOutput().getResourcesDir(),
65-
"META-INF/spring.factories"))
66-
.withPathSensitivity(PathSensitivity.RELATIVE).withPropertyName("spring.factories");
6761
getInputs()
6862
.file((Callable<File>) () -> new File(this.sourceSet.getOutput().getResourcesDir(),
6963
"META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports"))
@@ -99,9 +93,7 @@ void documentAutoConfiguration() throws IOException {
9993

10094
private Properties readAutoConfiguration() throws IOException {
10195
Properties autoConfiguration = CollectionFactory.createSortedProperties(true);
102-
Set<String> classNames = new LinkedHashSet<>();
103-
classNames.addAll(readSpringFactories());
104-
classNames.addAll(readAutoConfigurationsFile());
96+
List<String> classNames = readAutoConfigurationsFile();
10597
Set<String> publicClassNames = new LinkedHashSet<>();
10698
for (String className : classNames) {
10799
File classFile = findClassFile(className);
@@ -120,21 +112,6 @@ private Properties readAutoConfiguration() throws IOException {
120112
return autoConfiguration;
121113
}
122114

123-
/**
124-
* Reads auto-configurations from META-INF/spring.factories.
125-
* @return auto-configurations
126-
*/
127-
private Set<String> readSpringFactories() throws IOException {
128-
File file = new File(this.sourceSet.getOutput().getResourcesDir(), "META-INF/spring.factories");
129-
if (!file.exists()) {
130-
return Collections.emptySet();
131-
}
132-
Properties springFactories = readSpringFactories(file);
133-
String enableAutoConfiguration = springFactories
134-
.getProperty("org.springframework.boot.autoconfigure.EnableAutoConfiguration");
135-
return StringUtils.commaDelimitedListToSet(enableAutoConfiguration);
136-
}
137-
138115
/**
139116
* Reads auto-configurations from
140117
* META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports.
@@ -146,29 +123,18 @@ private List<String> readAutoConfigurationsFile() throws IOException {
146123
if (!file.exists()) {
147124
return Collections.emptyList();
148125
}
149-
// Nearly identical copy of
150-
// org.springframework.boot.context.annotation.ImportCandidates.load
151-
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)))) {
152-
List<String> autoConfigurations = new ArrayList<>();
153-
String line;
154-
while ((line = reader.readLine()) != null) {
155-
line = stripComment(line);
156-
line = line.trim();
157-
if (line.isEmpty()) {
158-
continue;
159-
}
160-
autoConfigurations.add(line);
161-
}
162-
return autoConfigurations;
126+
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
127+
return reader.lines().map(this::stripComment).filter((line) -> !line.isEmpty())
128+
.collect(Collectors.toList());
163129
}
164130
}
165131

166132
private String stripComment(String line) {
167133
int commentStart = line.indexOf(COMMENT_START);
168134
if (commentStart == -1) {
169-
return line;
135+
return line.trim();
170136
}
171-
return line.substring(0, commentStart);
137+
return line.substring(0, commentStart).trim();
172138
}
173139

174140
private File findClassFile(String className) {
@@ -182,12 +148,4 @@ private File findClassFile(String className) {
182148
return null;
183149
}
184150

185-
private Properties readSpringFactories(File file) throws IOException {
186-
Properties springFactories = new Properties();
187-
try (Reader in = new FileReader(file)) {
188-
springFactories.load(in);
189-
}
190-
return springFactories;
191-
}
192-
193151
}

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/ManagementContextConfigurationImportSelector.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
import org.springframework.core.OrderComparator;
3030
import org.springframework.core.Ordered;
3131
import org.springframework.core.annotation.Order;
32-
import org.springframework.core.io.support.SpringFactoriesLoader;
3332
import org.springframework.core.type.AnnotationMetadata;
3433
import org.springframework.core.type.classreading.MetadataReader;
3534
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
@@ -44,6 +43,7 @@
4443
* @author Phillip Webb
4544
* @author Andy Wilkinson
4645
* @author Moritz Halbritter
46+
* @author Scott Frederick
4747
* @see ManagementContextConfiguration
4848
* @see ImportCandidates
4949
*/
@@ -90,11 +90,7 @@ private void addConfiguration(SimpleMetadataReaderFactory readerFactory,
9090
}
9191

9292
protected List<String> loadFactoryNames() {
93-
@SuppressWarnings("deprecation")
94-
List<String> factoryNames = new ArrayList<>(
95-
SpringFactoriesLoader.loadFactoryNames(ManagementContextConfiguration.class, this.classLoader));
96-
ImportCandidates.load(ManagementContextConfiguration.class, this.classLoader).forEach(factoryNames::add);
97-
return factoryNames;
93+
return ImportCandidates.load(ManagementContextConfiguration.class, this.classLoader).getCandidates();
9894
}
9995

10096
@Override

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,13 @@
3030
import org.springframework.context.annotation.Conditional;
3131
import org.springframework.context.annotation.Configuration;
3232
import org.springframework.core.annotation.AliasFor;
33-
import org.springframework.core.io.support.SpringFactoriesLoader;
3433

3534
/**
3635
* Indicates that a class provides configuration that can be automatically applied by
3736
* Spring Boot. Auto-configuration classes are regular
3837
* {@link Configuration @Configuration} with the exception that
3938
* {@literal Configuration#proxyBeanMethods() proxyBeanMethods} is always {@code false}.
40-
* <p>
41-
* They are located using {@link ImportCandidates} and the {@link SpringFactoriesLoader}
42-
* mechanism (keyed against {@link EnableAutoConfiguration}).
39+
* They are located using {@link ImportCandidates}.
4340
* <p>
4441
* Generally auto-configuration classes are marked as {@link Conditional @Conditional}
4542
* (most often using {@link ConditionalOnClass @ConditionalOnClass} and

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

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,11 @@
1717
package org.springframework.boot.autoconfigure;
1818

1919
import java.io.IOException;
20-
import java.util.ArrayList;
2120
import java.util.List;
2221

2322
import org.springframework.beans.factory.BeanClassLoaderAware;
2423
import org.springframework.boot.context.annotation.ImportCandidates;
2524
import org.springframework.context.annotation.Configuration;
26-
import org.springframework.core.io.support.SpringFactoriesLoader;
2725
import org.springframework.core.type.classreading.MetadataReader;
2826
import org.springframework.core.type.classreading.MetadataReaderFactory;
2927
import org.springframework.core.type.filter.TypeFilter;
@@ -32,6 +30,7 @@
3230
* A {@link TypeFilter} implementation that matches registered auto-configuration classes.
3331
*
3432
* @author Stephane Nicoll
33+
* @author Scott Frederick
3534
* @since 1.5.0
3635
*/
3736
public class AutoConfigurationExcludeFilter implements TypeFilter, BeanClassLoaderAware {
@@ -64,11 +63,8 @@ private boolean isAutoConfiguration(MetadataReader metadataReader) {
6463

6564
protected List<String> getAutoConfigurations() {
6665
if (this.autoConfigurations == null) {
67-
@SuppressWarnings("deprecation")
68-
List<String> autoConfigurations = new ArrayList<>(
69-
SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class, this.beanClassLoader));
70-
ImportCandidates.load(AutoConfiguration.class, this.beanClassLoader).forEach(autoConfigurations::add);
71-
this.autoConfigurations = autoConfigurations;
66+
this.autoConfigurations = ImportCandidates.load(AutoConfiguration.class, this.beanClassLoader)
67+
.getCandidates();
7268
}
7369
return this.autoConfigurations;
7470
}

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

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
* @author Stephane Nicoll
7070
* @author Madhura Bhave
7171
* @author Moritz Halbritter
72+
* @author Scott Frederick
7273
* @since 1.3.0
7374
* @see EnableAutoConfiguration
7475
*/
@@ -168,36 +169,23 @@ protected Class<?> getAnnotationClass() {
168169
}
169170

170171
/**
171-
* Return the auto-configuration class names that should be considered. By default
172-
* this method will load candidates using {@link ImportCandidates} with
173-
* {@link #getSpringFactoriesLoaderFactoryClass()}. For backward compatible reasons it
174-
* will also consider {@link SpringFactoriesLoader} with
175-
* {@link #getSpringFactoriesLoaderFactoryClass()}.
172+
* Return the auto-configuration class names that should be considered. By default,
173+
* this method will load candidates using {@link ImportCandidates}.
176174
* @param metadata the source metadata
177175
* @param attributes the {@link #getAttributes(AnnotationMetadata) annotation
178176
* attributes}
179177
* @return a list of candidate configurations
180178
*/
181179
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
182-
@SuppressWarnings("deprecation")
183-
List<String> configurations = new ArrayList<>(
184-
SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()));
185-
ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()).forEach(configurations::add);
180+
List<String> configurations = ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader())
181+
.getCandidates();
186182
Assert.notEmpty(configurations,
187-
"No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you "
183+
"No auto configuration classes found in "
184+
+ "META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you "
188185
+ "are using a custom packaging, make sure that file is correct.");
189186
return configurations;
190187
}
191188

192-
/**
193-
* Return the class used by {@link SpringFactoriesLoader} to load configuration
194-
* candidates.
195-
* @return the factory class
196-
*/
197-
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
198-
return EnableAutoConfiguration.class;
199-
}
200-
201189
private void checkExcludedClasses(List<String> configurations, Set<String> exclusions) {
202190
List<String> invalidExcludes = new ArrayList<>(exclusions.size());
203191
for (String exclusion : exclusions) {

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
import org.springframework.context.annotation.Conditional;
3333
import org.springframework.context.annotation.Configuration;
3434
import org.springframework.context.annotation.Import;
35-
import org.springframework.core.io.support.SpringFactoriesLoader;
3635

3736
/**
3837
* Enable auto-configuration of the Spring Application Context, attempting to guess and
@@ -61,9 +60,8 @@
6160
* and classes can be searched.
6261
* <p>
6362
* Auto-configuration classes are regular Spring {@link Configuration @Configuration}
64-
* beans. They are located using {@link ImportCandidates} and the
65-
* {@link SpringFactoriesLoader} mechanism (keyed against this class). Generally
66-
* auto-configuration beans are {@link Conditional @Conditional} beans (most often using
63+
* beans. They are located using {@link ImportCandidates}. Generally auto-configuration
64+
* beans are {@link Conditional @Conditional} beans (most often using
6765
* {@link ConditionalOnClass @ConditionalOnClass} and
6866
* {@link ConditionalOnMissingBean @ConditionalOnMissingBean} annotations).
6967
*

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
import org.springframework.core.annotation.AnnotatedElementUtils;
3333
import org.springframework.core.annotation.AnnotationAttributes;
3434
import org.springframework.core.annotation.AnnotationUtils;
35-
import org.springframework.core.io.support.SpringFactoriesLoader;
3635
import org.springframework.core.type.AnnotationMetadata;
3736
import org.springframework.util.ClassUtils;
3837
import org.springframework.util.LinkedMultiValueMap;
@@ -46,6 +45,7 @@
4645
* @author Phillip Webb
4746
* @author Andy Wilkinson
4847
* @author Moritz Halbritter
48+
* @author Scott Frederick
4949
*/
5050
class ImportAutoConfigurationImportSelector extends AutoConfigurationImportSelector implements DeterminableImports {
5151

@@ -96,11 +96,7 @@ private Collection<String> getConfigurationsForAnnotation(Class<?> source, Annot
9696
}
9797

9898
protected Collection<String> loadFactoryNames(Class<?> source) {
99-
@SuppressWarnings("deprecation")
100-
List<String> factoryNames = new ArrayList<>(
101-
SpringFactoriesLoader.loadFactoryNames(source, getBeanClassLoader()));
102-
ImportCandidates.load(source, getBeanClassLoader()).forEach(factoryNames::add);
103-
return factoryNames;
99+
return ImportCandidates.load(source, getBeanClassLoader()).getCandidates();
104100
}
105101

106102
@Override

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -213,10 +213,7 @@ private String[] selectImports(Class<?> source) {
213213
}
214214

215215
private List<String> getAutoConfigurationClassNames() {
216-
List<String> autoConfigurationClassNames = new ArrayList<>();
217-
ImportCandidates.load(AutoConfiguration.class, getClass().getClassLoader())
218-
.forEach(autoConfigurationClassNames::add);
219-
return autoConfigurationClassNames;
216+
return ImportCandidates.load(AutoConfiguration.class, getClass().getClassLoader()).getCandidates();
220217
}
221218

222219
private class TestAutoConfigurationImportSelector extends AutoConfigurationImportSelector {

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/annotation/ImportCandidates.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
* candidates.
3838
*
3939
* @author Moritz Halbritter
40+
* @author Scott Frederick
4041
* @since 2.7.0
4142
*/
4243
public final class ImportCandidates implements Iterable<String> {
@@ -57,6 +58,14 @@ public Iterator<String> iterator() {
5758
return this.candidates.iterator();
5859
}
5960

61+
/**
62+
* Returns the list of loaded import candidates.
63+
* @return the list of import candidates
64+
*/
65+
public List<String> getCandidates() {
66+
return this.candidates;
67+
}
68+
6069
/**
6170
* Loads the names of import candidates from the classpath.
6271
*

0 commit comments

Comments
 (0)