Skip to content

Commit b6e4533

Browse files
committed
Add nullability annotations to core/spring-boot-autoconfigure
See gh-46587
1 parent 807f444 commit b6e4533

File tree

85 files changed

+665
-338
lines changed

Some content is hidden

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

85 files changed

+665
-338
lines changed

config/checkstyle/checkstyle-suppressions.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,5 @@
9090
<suppress files="PemPrivateKeyParser\.java" checks="NoWhitespaceBefore" message="'...' is preceded with whitespace"/>
9191
<suppress files="Bindable\.java" checks="NoWhitespaceBefore" message="'...' is preceded with whitespace"/>
9292
<suppress files="LambdaSafe\.java" checks="NoWhitespaceBefore" message="'...' is preceded with whitespace"/>
93+
<suppress files="ConditionMessage\.java" checks="NoWhitespaceBefore" message="'...' is preceded with whitespace"/>
9394
</suppressions>

core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AbstractDependsOnBeanFactoryPostProcessor.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import java.util.function.Function;
2323
import java.util.stream.Collectors;
2424

25+
import org.jspecify.annotations.Nullable;
26+
2527
import org.springframework.beans.factory.BeanFactory;
2628
import org.springframework.beans.factory.BeanFactoryUtils;
2729
import org.springframework.beans.factory.FactoryBean;
@@ -50,7 +52,7 @@ public abstract class AbstractDependsOnBeanFactoryPostProcessor implements BeanF
5052

5153
private final Class<?> beanClass;
5254

53-
private final Class<? extends FactoryBean<?>> factoryBeanClass;
55+
private final @Nullable Class<? extends FactoryBean<?>> factoryBeanClass;
5456

5557
private final Function<ListableBeanFactory, Set<String>> dependsOn;
5658

@@ -61,7 +63,7 @@ public abstract class AbstractDependsOnBeanFactoryPostProcessor implements BeanF
6163
* @param dependsOn dependency names
6264
*/
6365
protected AbstractDependsOnBeanFactoryPostProcessor(Class<?> beanClass,
64-
Class<? extends FactoryBean<?>> factoryBeanClass, String... dependsOn) {
66+
@Nullable Class<? extends FactoryBean<?>> factoryBeanClass, String... dependsOn) {
6567
this.beanClass = beanClass;
6668
this.factoryBeanClass = factoryBeanClass;
6769
this.dependsOn = (beanFactory) -> new HashSet<>(Arrays.asList(dependsOn));
@@ -75,7 +77,7 @@ protected AbstractDependsOnBeanFactoryPostProcessor(Class<?> beanClass,
7577
* @since 2.1.7
7678
*/
7779
protected AbstractDependsOnBeanFactoryPostProcessor(Class<?> beanClass,
78-
Class<? extends FactoryBean<?>> factoryBeanClass, Class<?>... dependencyTypes) {
80+
@Nullable Class<? extends FactoryBean<?>> factoryBeanClass, Class<?>... dependencyTypes) {
7981
this.beanClass = beanClass;
8082
this.factoryBeanClass = factoryBeanClass;
8183
this.dependsOn = (beanFactory) -> Arrays.stream(dependencyTypes)

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,15 @@
1919
import java.io.IOException;
2020
import java.util.List;
2121

22+
import org.jspecify.annotations.Nullable;
23+
2224
import org.springframework.beans.factory.BeanClassLoaderAware;
2325
import org.springframework.boot.context.annotation.ImportCandidates;
2426
import org.springframework.context.annotation.Configuration;
2527
import org.springframework.core.type.classreading.MetadataReader;
2628
import org.springframework.core.type.classreading.MetadataReaderFactory;
2729
import org.springframework.core.type.filter.TypeFilter;
30+
import org.springframework.util.Assert;
2831

2932
/**
3033
* A {@link TypeFilter} implementation that matches registered auto-configuration classes.
@@ -35,9 +38,10 @@
3538
*/
3639
public class AutoConfigurationExcludeFilter implements TypeFilter, BeanClassLoaderAware {
3740

41+
@SuppressWarnings("NullAway.Init")
3842
private ClassLoader beanClassLoader;
3943

40-
private volatile List<String> autoConfigurations;
44+
private volatile @Nullable List<String> autoConfigurations;
4145

4246
@Override
4347
public void setBeanClassLoader(ClassLoader beanClassLoader) {
@@ -66,6 +70,7 @@ protected List<String> getAutoConfigurations() {
6670
ImportCandidates importCandidates = ImportCandidates.load(AutoConfiguration.class, this.beanClassLoader);
6771
this.autoConfigurations = importCandidates.getCandidates();
6872
}
73+
Assert.state(this.autoConfigurations != null, "'autoConfigurations' must not be null");
6974
return this.autoConfigurations;
7075
}
7176

core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationImportFilter.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.boot.autoconfigure;
1818

19+
import org.jspecify.annotations.Nullable;
20+
1921
import org.springframework.beans.factory.BeanClassLoaderAware;
2022
import org.springframework.beans.factory.BeanFactoryAware;
2123
import org.springframework.context.EnvironmentAware;
@@ -54,6 +56,6 @@ public interface AutoConfigurationImportFilter {
5456
* {@code autoConfigurationClasses} parameter. Entries containing {@code false} will
5557
* not be imported.
5658
*/
57-
boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata);
59+
boolean[] match(@Nullable String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata);
5860

5961
}

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

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
import org.apache.commons.logging.Log;
3434
import org.apache.commons.logging.LogFactory;
35+
import org.jspecify.annotations.Nullable;
3536

3637
import org.springframework.beans.BeansException;
3738
import org.springframework.beans.factory.Aware;
@@ -89,23 +90,27 @@ public class AutoConfigurationImportSelector implements DeferredImportSelector,
8990

9091
private final Class<?> autoConfigurationAnnotation;
9192

93+
@SuppressWarnings("NullAway.Init")
9294
private ConfigurableListableBeanFactory beanFactory;
9395

96+
@SuppressWarnings("NullAway.Init")
9497
private Environment environment;
9598

99+
@SuppressWarnings("NullAway.Init")
96100
private ClassLoader beanClassLoader;
97101

102+
@SuppressWarnings("NullAway.Init")
98103
private ResourceLoader resourceLoader;
99104

100-
private volatile ConfigurationClassFilter configurationClassFilter;
105+
private volatile @Nullable ConfigurationClassFilter configurationClassFilter;
101106

102-
private volatile AutoConfigurationReplacements autoConfigurationReplacements;
107+
private volatile @Nullable AutoConfigurationReplacements autoConfigurationReplacements;
103108

104109
public AutoConfigurationImportSelector() {
105110
this(null);
106111
}
107112

108-
AutoConfigurationImportSelector(Class<?> autoConfigurationAnnotation) {
113+
AutoConfigurationImportSelector(@Nullable Class<?> autoConfigurationAnnotation) {
109114
this.autoConfigurationAnnotation = (autoConfigurationAnnotation != null) ? autoConfigurationAnnotation
110115
: AutoConfiguration.class;
111116
}
@@ -168,7 +173,7 @@ protected boolean isEnabled(AnnotationMetadata metadata) {
168173
* @param metadata the annotation metadata
169174
* @return annotation attributes
170175
*/
171-
protected AnnotationAttributes getAttributes(AnnotationMetadata metadata) {
176+
protected @Nullable AnnotationAttributes getAttributes(AnnotationMetadata metadata) {
172177
String name = getAnnotationClass().getName();
173178
AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(name, true));
174179
Assert.state(attributes != null, () -> "No auto-configuration attributes found. Is " + metadata.getClassName()
@@ -192,7 +197,8 @@ protected Class<?> getAnnotationClass() {
192197
* attributes}
193198
* @return a list of candidate configurations
194199
*/
195-
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
200+
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
201+
@Nullable AnnotationAttributes attributes) {
196202
ImportCandidates importCandidates = ImportCandidates.load(this.autoConfigurationAnnotation,
197203
getBeanClassLoader());
198204
List<String> configurations = importCandidates.getCandidates();
@@ -237,10 +243,12 @@ protected void handleInvalidExcludes(List<String> invalidExcludes) {
237243
* attributes}
238244
* @return exclusions or an empty set
239245
*/
240-
protected Set<String> getExclusions(AnnotationMetadata metadata, AnnotationAttributes attributes) {
246+
protected Set<String> getExclusions(AnnotationMetadata metadata, @Nullable AnnotationAttributes attributes) {
241247
Set<String> excluded = new LinkedHashSet<>();
242-
excluded.addAll(asList(attributes, "exclude"));
243-
excluded.addAll(asList(attributes, "excludeName"));
248+
if (attributes != null) {
249+
excluded.addAll(asList(attributes, "exclude"));
250+
excluded.addAll(asList(attributes, "excludeName"));
251+
}
244252
excluded.addAll(getExcludeAutoConfigurationsProperty());
245253
return getAutoConfigurationReplacements().replaceAll(excluded);
246254
}
@@ -389,7 +397,7 @@ private static class ConfigurationClassFilter {
389397

390398
List<String> filter(List<String> configurations) {
391399
long startTime = System.nanoTime();
392-
String[] candidates = StringUtils.toStringArray(configurations);
400+
@Nullable String[] candidates = StringUtils.toStringArray(configurations);
393401
boolean skipped = false;
394402
for (AutoConfigurationImportFilter filter : this.filters) {
395403
boolean[] match = filter.match(candidates, this.autoConfigurationMetadata);
@@ -426,15 +434,18 @@ private static final class AutoConfigurationGroup
426434

427435
private final List<AutoConfigurationEntry> autoConfigurationEntries = new ArrayList<>();
428436

437+
@SuppressWarnings("NullAway.Init")
429438
private ClassLoader beanClassLoader;
430439

440+
@SuppressWarnings("NullAway.Init")
431441
private BeanFactory beanFactory;
432442

443+
@SuppressWarnings("NullAway.Init")
433444
private ResourceLoader resourceLoader;
434445

435-
private AutoConfigurationMetadata autoConfigurationMetadata;
446+
private @Nullable AutoConfigurationMetadata autoConfigurationMetadata;
436447

437-
private AutoConfigurationReplacements autoConfigurationReplacements;
448+
private @Nullable AutoConfigurationReplacements autoConfigurationReplacements;
438449

439450
@Override
440451
public void setBeanClassLoader(ClassLoader classLoader) {
@@ -488,10 +499,16 @@ public Iterable<Entry> selectImports() {
488499
.collect(Collectors.toCollection(LinkedHashSet::new));
489500
processedConfigurations.removeAll(allExclusions);
490501
return sortAutoConfigurations(processedConfigurations, getAutoConfigurationMetadata()).stream()
491-
.map((importClassName) -> new Entry(this.entries.get(importClassName), importClassName))
502+
.map(this::getEntry)
492503
.toList();
493504
}
494505

506+
private Entry getEntry(String importClassName) {
507+
AnnotationMetadata metadata = this.entries.get(importClassName);
508+
Assert.state(metadata != null, "'metadata' must not be null");
509+
return new Entry(metadata, importClassName);
510+
}
511+
495512
private AutoConfigurationMetadata getAutoConfigurationMetadata() {
496513
if (this.autoConfigurationMetadata == null) {
497514
this.autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
@@ -501,6 +518,8 @@ private AutoConfigurationMetadata getAutoConfigurationMetadata() {
501518

502519
private List<String> sortAutoConfigurations(Set<String> configurations,
503520
AutoConfigurationMetadata autoConfigurationMetadata) {
521+
Assert.state(this.autoConfigurationReplacements != null,
522+
"'autoConfigurationReplacements' must not be null");
504523
return new AutoConfigurationSorter(getMetadataReaderFactory(), autoConfigurationMetadata,
505524
this.autoConfigurationReplacements::replace)
506525
.getInPriorityOrder(configurations);

core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationMetadata.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818

1919
import java.util.Set;
2020

21+
import org.jspecify.annotations.Nullable;
22+
23+
import org.springframework.lang.Contract;
24+
2125
/**
2226
* Provides access to meta-data written by the auto-configure annotation processor.
2327
*
@@ -40,7 +44,7 @@ public interface AutoConfigurationMetadata {
4044
* @param key the meta-data key
4145
* @return the meta-data value or {@code null}
4246
*/
43-
Integer getInteger(String className, String key);
47+
@Nullable Integer getInteger(String className, String key);
4448

4549
/**
4650
* Get an {@link Integer} value from the meta-data.
@@ -49,15 +53,16 @@ public interface AutoConfigurationMetadata {
4953
* @param defaultValue the default value
5054
* @return the meta-data value or {@code defaultValue}
5155
*/
52-
Integer getInteger(String className, String key, Integer defaultValue);
56+
@Contract("_, _, !null -> !null")
57+
@Nullable Integer getInteger(String className, String key, @Nullable Integer defaultValue);
5358

5459
/**
5560
* Get a {@link Set} value from the meta-data.
5661
* @param className the source class
5762
* @param key the meta-data key
5863
* @return the meta-data value or {@code null}
5964
*/
60-
Set<String> getSet(String className, String key);
65+
@Nullable Set<String> getSet(String className, String key);
6166

6267
/**
6368
* Get a {@link Set} value from the meta-data.
@@ -66,15 +71,16 @@ public interface AutoConfigurationMetadata {
6671
* @param defaultValue the default value
6772
* @return the meta-data value or {@code defaultValue}
6873
*/
69-
Set<String> getSet(String className, String key, Set<String> defaultValue);
74+
@Contract("_, _, !null -> !null")
75+
@Nullable Set<String> getSet(String className, String key, @Nullable Set<String> defaultValue);
7076

7177
/**
7278
* Get an {@link String} value from the meta-data.
7379
* @param className the source class
7480
* @param key the meta-data key
7581
* @return the meta-data value or {@code null}
7682
*/
77-
String get(String className, String key);
83+
@Nullable String get(String className, String key);
7884

7985
/**
8086
* Get an {@link String} value from the meta-data.
@@ -83,6 +89,7 @@ public interface AutoConfigurationMetadata {
8389
* @param defaultValue the default value
8490
* @return the meta-data value or {@code defaultValue}
8591
*/
86-
String get(String className, String key, String defaultValue);
92+
@Contract("_, _, !null -> !null")
93+
@Nullable String get(String className, String key, @Nullable String defaultValue);
8794

8895
}

core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationMetadataLoader.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import java.util.Properties;
2323
import java.util.Set;
2424

25+
import org.jspecify.annotations.Nullable;
26+
2527
import org.springframework.core.io.UrlResource;
2628
import org.springframework.core.io.support.PropertiesLoaderUtils;
2729
import org.springframework.util.StringUtils;
@@ -42,7 +44,7 @@ static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader) {
4244
return loadMetadata(classLoader, PATH);
4345
}
4446

45-
static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader, String path) {
47+
static AutoConfigurationMetadata loadMetadata(@Nullable ClassLoader classLoader, String path) {
4648
try {
4749
Enumeration<URL> urls = (classLoader != null) ? classLoader.getResources(path)
4850
: ClassLoader.getSystemResources(path);
@@ -78,34 +80,34 @@ public boolean wasProcessed(String className) {
7880
}
7981

8082
@Override
81-
public Integer getInteger(String className, String key) {
83+
public @Nullable Integer getInteger(String className, String key) {
8284
return getInteger(className, key, null);
8385
}
8486

8587
@Override
86-
public Integer getInteger(String className, String key, Integer defaultValue) {
88+
public @Nullable Integer getInteger(String className, String key, @Nullable Integer defaultValue) {
8789
String value = get(className, key);
8890
return (value != null) ? Integer.valueOf(value) : defaultValue;
8991
}
9092

9193
@Override
92-
public Set<String> getSet(String className, String key) {
94+
public @Nullable Set<String> getSet(String className, String key) {
9395
return getSet(className, key, null);
9496
}
9597

9698
@Override
97-
public Set<String> getSet(String className, String key, Set<String> defaultValue) {
99+
public @Nullable Set<String> getSet(String className, String key, @Nullable Set<String> defaultValue) {
98100
String value = get(className, key);
99101
return (value != null) ? StringUtils.commaDelimitedListToSet(value) : defaultValue;
100102
}
101103

102104
@Override
103-
public String get(String className, String key) {
105+
public @Nullable String get(String className, String key) {
104106
return get(className, key, null);
105107
}
106108

107109
@Override
108-
public String get(String className, String key, String defaultValue) {
110+
public @Nullable String get(String className, String key, @Nullable String defaultValue) {
109111
String value = this.properties.getProperty(className + "." + key);
110112
return (value != null) ? value : defaultValue;
111113
}

core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationPackages.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,14 @@
3030
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
3131
import org.springframework.beans.factory.config.BeanDefinition;
3232
import org.springframework.beans.factory.config.ConstructorArgumentValues;
33+
import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
3334
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
3435
import org.springframework.beans.factory.support.RootBeanDefinition;
3536
import org.springframework.boot.context.annotation.DeterminableImports;
3637
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
3738
import org.springframework.core.annotation.AnnotationAttributes;
3839
import org.springframework.core.type.AnnotationMetadata;
40+
import org.springframework.util.Assert;
3941
import org.springframework.util.ClassUtils;
4042
import org.springframework.util.StringUtils;
4143

@@ -105,8 +107,9 @@ public static void register(BeanDefinitionRegistry registry, String... packageNa
105107
private static void addBasePackages(BeanDefinition beanDefinition, String[] additionalBasePackages) {
106108
ConstructorArgumentValues constructorArgumentValues = beanDefinition.getConstructorArgumentValues();
107109
if (constructorArgumentValues.hasIndexedArgumentValue(0)) {
108-
String[] existingPackages = (String[]) constructorArgumentValues.getIndexedArgumentValue(0, String[].class)
109-
.getValue();
110+
ValueHolder indexedArgumentValue = constructorArgumentValues.getIndexedArgumentValue(0, String[].class);
111+
Assert.state(indexedArgumentValue != null, "'indexedArgumentValue' must not be null");
112+
String[] existingPackages = (String[]) indexedArgumentValue.getValue();
110113
constructorArgumentValues.addIndexedArgumentValue(0,
111114
Stream.concat(Stream.of(existingPackages), Stream.of(additionalBasePackages))
112115
.distinct()
@@ -145,6 +148,7 @@ private static final class PackageImports {
145148
PackageImports(AnnotationMetadata metadata) {
146149
AnnotationAttributes attributes = AnnotationAttributes
147150
.fromMap(metadata.getAnnotationAttributes(AutoConfigurationPackage.class.getName(), false));
151+
Assert.state(attributes != null, "'attributes' must not be null");
148152
List<String> packageNames = new ArrayList<>(Arrays.asList(attributes.getStringArray("basePackages")));
149153
for (Class<?> basePackageClass : attributes.getClassArray("basePackageClasses")) {
150154
packageNames.add(basePackageClass.getPackage().getName());

0 commit comments

Comments
 (0)