mirror of
https://github.com/spring-projects/spring-boot.git
synced 2026-09-17 12:09:16 +00:00
Add nullability annotations to core/spring-boot
See gh-46587
This commit is contained in:
@@ -86,4 +86,8 @@
|
||||
<suppress files="ConfigurationPropertyCaching\.java" checks="SpringJavadoc" message="\@since"/>
|
||||
<suppress files="StructuredLoggingJsonMembersCustomizer\.java" checks="SpringJavadoc" message="\@since"/>
|
||||
<suppress files="FieldValues\.java" checks="SimplifyBooleanExpression" />
|
||||
<!-- jspecify: https://github.com/spring-io/spring-javaformat/issues/454 -->
|
||||
<suppress files="PemPrivateKeyParser\.java" checks="NoWhitespaceBefore" message="'...' is preceded with whitespace"/>
|
||||
<suppress files="Bindable\.java" checks="NoWhitespaceBefore" message="'...' is preceded with whitespace"/>
|
||||
<suppress files="LambdaSafe\.java" checks="NoWhitespaceBefore" message="'...' is preceded with whitespace"/>
|
||||
</suppressions>
|
||||
|
||||
@@ -19,6 +19,8 @@ package org.springframework.boot;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Provides access to the arguments that were used to run a {@link SpringApplication}.
|
||||
*
|
||||
@@ -63,7 +65,7 @@ public interface ApplicationArguments {
|
||||
* @param name the name of the option
|
||||
* @return a list of option values for the given name
|
||||
*/
|
||||
List<String> getOptionValues(String name);
|
||||
@Nullable List<String> getOptionValues(String name);
|
||||
|
||||
/**
|
||||
* Return the collection of non-option arguments parsed.
|
||||
|
||||
+8
-5
@@ -18,6 +18,8 @@ package org.springframework.boot;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
@@ -46,11 +48,12 @@ public interface ApplicationContextFactory {
|
||||
* Return the {@link Environment} type expected to be set on the
|
||||
* {@link #create(WebApplicationType) created} application context. The result of this
|
||||
* method can be used to convert an existing environment instance to the correct type.
|
||||
* @param webApplicationType the web application type
|
||||
* @param webApplicationType the web application type or {@code null}
|
||||
* @return the expected application context type or {@code null} to use the default
|
||||
* @since 2.6.14
|
||||
*/
|
||||
default Class<? extends ConfigurableEnvironment> getEnvironmentType(WebApplicationType webApplicationType) {
|
||||
default @Nullable Class<? extends ConfigurableEnvironment> getEnvironmentType(
|
||||
@Nullable WebApplicationType webApplicationType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -59,11 +62,11 @@ public interface ApplicationContextFactory {
|
||||
* {@link #create(WebApplicationType) created} application context. The result of this
|
||||
* method must match the type returned by
|
||||
* {@link #getEnvironmentType(WebApplicationType)}.
|
||||
* @param webApplicationType the web application type
|
||||
* @param webApplicationType the web application type or {@code null}
|
||||
* @return an environment instance or {@code null} to use the default
|
||||
* @since 2.6.14
|
||||
*/
|
||||
default ConfigurableEnvironment createEnvironment(WebApplicationType webApplicationType) {
|
||||
default @Nullable ConfigurableEnvironment createEnvironment(@Nullable WebApplicationType webApplicationType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -73,7 +76,7 @@ public interface ApplicationContextFactory {
|
||||
* @param webApplicationType the web application type
|
||||
* @return the newly created application context
|
||||
*/
|
||||
ConfigurableApplicationContext create(WebApplicationType webApplicationType);
|
||||
ConfigurableApplicationContext create(@Nullable WebApplicationType webApplicationType);
|
||||
|
||||
/**
|
||||
* Creates an {@code ApplicationContextFactory} that will create contexts by
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.boot;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
|
||||
import org.springframework.core.env.ConfigurablePropertyResolver;
|
||||
import org.springframework.core.env.MutablePropertySources;
|
||||
@@ -29,12 +31,12 @@ import org.springframework.core.env.StandardEnvironment;
|
||||
class ApplicationEnvironment extends StandardEnvironment {
|
||||
|
||||
@Override
|
||||
protected String doGetActiveProfilesProperty() {
|
||||
protected @Nullable String doGetActiveProfilesProperty() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doGetDefaultProfilesProperty() {
|
||||
protected @Nullable String doGetDefaultProfilesProperty() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+6
-4
@@ -19,6 +19,8 @@ package org.springframework.boot;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.origin.Origin;
|
||||
import org.springframework.boot.origin.OriginLookup;
|
||||
import org.springframework.boot.system.ApplicationPid;
|
||||
@@ -38,7 +40,7 @@ class ApplicationInfoPropertySource extends MapPropertySource implements OriginL
|
||||
|
||||
static final String NAME = "applicationInfo";
|
||||
|
||||
ApplicationInfoPropertySource(Class<?> mainClass) {
|
||||
ApplicationInfoPropertySource(@Nullable Class<?> mainClass) {
|
||||
super(NAME, getProperties(readVersion(mainClass)));
|
||||
}
|
||||
|
||||
@@ -47,7 +49,7 @@ class ApplicationInfoPropertySource extends MapPropertySource implements OriginL
|
||||
}
|
||||
|
||||
@Override
|
||||
public Origin getOrigin(String key) {
|
||||
public @Nullable Origin getOrigin(String key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -56,7 +58,7 @@ class ApplicationInfoPropertySource extends MapPropertySource implements OriginL
|
||||
return true;
|
||||
}
|
||||
|
||||
private static Map<String, Object> getProperties(String applicationVersion) {
|
||||
private static Map<String, Object> getProperties(@Nullable String applicationVersion) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
if (StringUtils.hasText(applicationVersion)) {
|
||||
result.put("spring.application.version", applicationVersion);
|
||||
@@ -68,7 +70,7 @@ class ApplicationInfoPropertySource extends MapPropertySource implements OriginL
|
||||
return result;
|
||||
}
|
||||
|
||||
private static String readVersion(Class<?> applicationClass) {
|
||||
private static @Nullable String readVersion(@Nullable Class<?> applicationClass) {
|
||||
Package sourcePackage = (applicationClass != null) ? applicationClass.getPackage() : null;
|
||||
return (sourcePackage != null) ? sourcePackage.getImplementationVersion() : null;
|
||||
}
|
||||
|
||||
@@ -19,12 +19,15 @@ package org.springframework.boot;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.aot.hint.RuntimeHintsRegistrar;
|
||||
import org.springframework.boot.Banner.Mode;
|
||||
import org.springframework.boot.context.properties.bind.BindableRuntimeHintsRegistrar;
|
||||
import org.springframework.boot.logging.LoggingSystemProperty;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Spring application properties.
|
||||
@@ -48,7 +51,7 @@ class ApplicationProperties {
|
||||
/**
|
||||
* Mode used to display the banner when the application runs.
|
||||
*/
|
||||
private Banner.Mode bannerMode;
|
||||
private Banner.@Nullable Mode bannerMode;
|
||||
|
||||
/**
|
||||
* Whether to keep the application alive even if there are no more non-daemon threads.
|
||||
@@ -80,7 +83,7 @@ class ApplicationProperties {
|
||||
* Flag to explicitly request a specific type of web application. If not set,
|
||||
* auto-detected based on the classpath.
|
||||
*/
|
||||
private WebApplicationType webApplicationType;
|
||||
private @Nullable WebApplicationType webApplicationType;
|
||||
|
||||
boolean isAllowBeanDefinitionOverriding() {
|
||||
return this.allowBeanDefinitionOverriding;
|
||||
@@ -102,12 +105,13 @@ class ApplicationProperties {
|
||||
if (this.bannerMode != null) {
|
||||
return this.bannerMode;
|
||||
}
|
||||
boolean structuredLoggingEnabled = environment
|
||||
.containsProperty(LoggingSystemProperty.CONSOLE_STRUCTURED_FORMAT.getApplicationPropertyName());
|
||||
String applicationPropertyName = LoggingSystemProperty.CONSOLE_STRUCTURED_FORMAT.getApplicationPropertyName();
|
||||
Assert.state(applicationPropertyName != null, "applicationPropertyName must not be null");
|
||||
boolean structuredLoggingEnabled = environment.containsProperty(applicationPropertyName);
|
||||
return (structuredLoggingEnabled) ? Mode.OFF : Banner.Mode.CONSOLE;
|
||||
}
|
||||
|
||||
void setBannerMode(Mode bannerMode) {
|
||||
void setBannerMode(@Nullable Mode bannerMode) {
|
||||
this.bannerMode = bannerMode;
|
||||
}
|
||||
|
||||
@@ -151,18 +155,18 @@ class ApplicationProperties {
|
||||
this.sources = new LinkedHashSet<>(sources);
|
||||
}
|
||||
|
||||
WebApplicationType getWebApplicationType() {
|
||||
@Nullable WebApplicationType getWebApplicationType() {
|
||||
return this.webApplicationType;
|
||||
}
|
||||
|
||||
void setWebApplicationType(WebApplicationType webApplicationType) {
|
||||
void setWebApplicationType(@Nullable WebApplicationType webApplicationType) {
|
||||
this.webApplicationType = webApplicationType;
|
||||
}
|
||||
|
||||
static class ApplicationPropertiesRuntimeHints implements RuntimeHintsRegistrar {
|
||||
|
||||
@Override
|
||||
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
|
||||
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
|
||||
BindableRuntimeHintsRegistrar.forTypes(ApplicationProperties.class).registerHints(hints, classLoader);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ package org.springframework.boot;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
/**
|
||||
@@ -34,10 +36,10 @@ public interface Banner {
|
||||
/**
|
||||
* Print the banner to the specified print stream.
|
||||
* @param environment the spring environment
|
||||
* @param sourceClass the source class for the application
|
||||
* @param sourceClass the source class for the application or {@code null}
|
||||
* @param out the output print stream
|
||||
*/
|
||||
void printBanner(Environment environment, Class<?> sourceClass, PrintStream out);
|
||||
void printBanner(Environment environment, @Nullable Class<?> sourceClass, PrintStream out);
|
||||
|
||||
/**
|
||||
* An enumeration of possible values for configuring the Banner.
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import groovy.lang.Closure;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
@@ -68,11 +69,11 @@ class BeanDefinitionLoader {
|
||||
|
||||
private final AbstractBeanDefinitionReader xmlReader;
|
||||
|
||||
private final BeanDefinitionReader groovyReader;
|
||||
private final @Nullable BeanDefinitionReader groovyReader;
|
||||
|
||||
private final ClassPathBeanDefinitionScanner scanner;
|
||||
|
||||
private ResourceLoader resourceLoader;
|
||||
private @Nullable ResourceLoader resourceLoader;
|
||||
|
||||
/**
|
||||
* Create a new {@link BeanDefinitionLoader} that will load beans into the specified
|
||||
@@ -86,7 +87,7 @@ class BeanDefinitionLoader {
|
||||
this.sources = sources;
|
||||
this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);
|
||||
this.xmlReader = new XmlBeanDefinitionReader(registry);
|
||||
this.groovyReader = (isGroovyPresent() ? new GroovyBeanDefinitionReader(registry) : null);
|
||||
this.groovyReader = isGroovyPresent() ? new GroovyBeanDefinitionReader(registry) : null;
|
||||
this.scanner = new ClassPathBeanDefinitionScanner(registry);
|
||||
this.scanner.addExcludeFilter(new ClassExcludeFilter(sources));
|
||||
}
|
||||
@@ -152,7 +153,7 @@ class BeanDefinitionLoader {
|
||||
}
|
||||
|
||||
private void load(Class<?> source) {
|
||||
if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
|
||||
if (this.groovyReader != null && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
|
||||
// Any GroovyLoaders added in beans{} DSL can contribute beans here
|
||||
GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class);
|
||||
((GroovyBeanDefinitionReader) this.groovyReader).beans(loader.getBeans());
|
||||
@@ -163,7 +164,9 @@ class BeanDefinitionLoader {
|
||||
}
|
||||
|
||||
private void load(Resource source) {
|
||||
if (source.getFilename().endsWith(".groovy")) {
|
||||
String filename = source.getFilename();
|
||||
Assert.state(filename != null, "Source has no filename");
|
||||
if (filename.endsWith(".groovy")) {
|
||||
if (this.groovyReader == null) {
|
||||
throw new BeanDefinitionStoreException("Cannot load Groovy beans without Groovy on classpath");
|
||||
}
|
||||
@@ -231,7 +234,7 @@ class BeanDefinitionLoader {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isLoadCandidate(Resource resource) {
|
||||
private boolean isLoadCandidate(@Nullable Resource resource) {
|
||||
if (resource == null || !resource.exists()) {
|
||||
return false;
|
||||
}
|
||||
@@ -253,7 +256,7 @@ class BeanDefinitionLoader {
|
||||
return true;
|
||||
}
|
||||
|
||||
private Package findPackage(CharSequence source) {
|
||||
private @Nullable Package findPackage(CharSequence source) {
|
||||
Package pkg = getClass().getClassLoader().getDefinedPackage(source.toString());
|
||||
if (pkg != null) {
|
||||
return pkg;
|
||||
@@ -264,7 +267,9 @@ class BeanDefinitionLoader {
|
||||
Resource[] resources = resolver
|
||||
.getResources(ClassUtils.convertClassNameToResourcePath(source.toString()) + "/*.class");
|
||||
for (Resource resource : resources) {
|
||||
String className = StringUtils.stripFilenameExtension(resource.getFilename());
|
||||
String filename = resource.getFilename();
|
||||
Assert.state(filename != null, "No filename available");
|
||||
String className = StringUtils.stripFilenameExtension(filename);
|
||||
load(Class.forName(source + "." + className));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ package org.springframework.boot;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
@@ -41,7 +43,7 @@ public interface BootstrapContext {
|
||||
* @return the instance managed by the context
|
||||
* @throws IllegalStateException if the type has not been registered
|
||||
*/
|
||||
<T> T get(Class<T> type) throws IllegalStateException;
|
||||
<T> @Nullable T get(Class<T> type) throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Return an instance from the context if the type has been registered. The instance
|
||||
@@ -51,7 +53,7 @@ public interface BootstrapContext {
|
||||
* @param other the instance to use if the type has not been registered
|
||||
* @return the instance
|
||||
*/
|
||||
<T> T getOrElse(Class<T> type, T other);
|
||||
<T> @Nullable T getOrElse(Class<T> type, @Nullable T other);
|
||||
|
||||
/**
|
||||
* Return an instance from the context if the type has been registered. The instance
|
||||
@@ -61,7 +63,7 @@ public interface BootstrapContext {
|
||||
* @param other a supplier for the instance to use if the type has not been registered
|
||||
* @return the instance
|
||||
*/
|
||||
<T> T getOrElseSupply(Class<T> type, Supplier<T> other);
|
||||
<T> @Nullable T getOrElseSupply(Class<T> type, Supplier<@Nullable T> other);
|
||||
|
||||
/**
|
||||
* Return an instance from the context if the type has been registered. The instance
|
||||
@@ -74,7 +76,8 @@ public interface BootstrapContext {
|
||||
* @throws X if the type has not been registered
|
||||
* @throws IllegalStateException if the type has not been registered
|
||||
*/
|
||||
<T, X extends Throwable> T getOrElseThrow(Class<T> type, Supplier<? extends X> exceptionSupplier) throws X;
|
||||
<T, X extends Throwable> @Nullable T getOrElseThrow(Class<T> type, Supplier<? extends X> exceptionSupplier)
|
||||
throws X;
|
||||
|
||||
/**
|
||||
* Return if a registration exists for the given type.
|
||||
|
||||
@@ -18,6 +18,8 @@ package org.springframework.boot;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.core.env.Environment;
|
||||
@@ -78,7 +80,7 @@ public interface BootstrapRegistry {
|
||||
* @param type the instance type
|
||||
* @return the registered {@link InstanceSupplier} or {@code null}
|
||||
*/
|
||||
<T> InstanceSupplier<T> getRegisteredInstanceSupplier(Class<T> type);
|
||||
<T> @Nullable InstanceSupplier<T> getRegisteredInstanceSupplier(Class<T> type);
|
||||
|
||||
/**
|
||||
* Add an {@link ApplicationListener} that will be called with a
|
||||
@@ -101,9 +103,9 @@ public interface BootstrapRegistry {
|
||||
* Factory method used to create the instance when needed.
|
||||
* @param context the {@link BootstrapContext} which may be used to obtain other
|
||||
* bootstrap instances.
|
||||
* @return the instance
|
||||
* @return the instance or {@code null}
|
||||
*/
|
||||
T get(BootstrapContext context);
|
||||
@Nullable T get(BootstrapContext context);
|
||||
|
||||
/**
|
||||
* Return the scope of the supplied instance.
|
||||
@@ -126,7 +128,7 @@ public interface BootstrapRegistry {
|
||||
return new InstanceSupplier<>() {
|
||||
|
||||
@Override
|
||||
public T get(BootstrapContext context) {
|
||||
public @Nullable T get(BootstrapContext context) {
|
||||
return parent.get(context);
|
||||
}
|
||||
|
||||
@@ -145,7 +147,7 @@ public interface BootstrapRegistry {
|
||||
* @param instance the instance
|
||||
* @return a new {@link InstanceSupplier}
|
||||
*/
|
||||
static <T> InstanceSupplier<T> of(T instance) {
|
||||
static <T> InstanceSupplier<T> of(@Nullable T instance) {
|
||||
return (registry) -> instance;
|
||||
}
|
||||
|
||||
@@ -156,7 +158,7 @@ public interface BootstrapRegistry {
|
||||
* @param supplier the supplier that will provide the instance
|
||||
* @return a new {@link InstanceSupplier}
|
||||
*/
|
||||
static <T> InstanceSupplier<T> from(Supplier<T> supplier) {
|
||||
static <T> InstanceSupplier<T> from(@Nullable Supplier<T> supplier) {
|
||||
return (registry) -> (supplier != null) ? supplier.get() : null;
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -18,6 +18,8 @@ package org.springframework.boot;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
@@ -35,7 +37,7 @@ class ClearCachesApplicationListener implements ApplicationListener<ContextRefre
|
||||
clearClassLoaderCaches(Thread.currentThread().getContextClassLoader());
|
||||
}
|
||||
|
||||
private void clearClassLoaderCaches(ClassLoader classLoader) {
|
||||
private void clearClassLoaderCaches(@Nullable ClassLoader classLoader) {
|
||||
if (classLoader == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
+4
-2
@@ -22,6 +22,8 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.env.SimpleCommandLinePropertySource;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -60,7 +62,7 @@ public class DefaultApplicationArguments implements ApplicationArguments {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getOptionValues(String name) {
|
||||
public @Nullable List<String> getOptionValues(String name) {
|
||||
List<String> values = this.source.getOptionValues(name);
|
||||
return (values != null) ? Collections.unmodifiableList(values) : null;
|
||||
}
|
||||
@@ -82,7 +84,7 @@ public class DefaultApplicationArguments implements ApplicationArguments {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getOptionValues(String name) {
|
||||
public @Nullable List<String> getOptionValues(String name) {
|
||||
return super.getOptionValues(name);
|
||||
}
|
||||
|
||||
|
||||
+17
-5
@@ -19,12 +19,15 @@ package org.springframework.boot;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.aot.AotDetector;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
import org.springframework.lang.Contract;
|
||||
|
||||
/**
|
||||
* Default {@link ApplicationContextFactory} implementation that will create an
|
||||
@@ -34,18 +37,25 @@ import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
*/
|
||||
class DefaultApplicationContextFactory implements ApplicationContextFactory {
|
||||
|
||||
// Method reference is not detected with correct nullability
|
||||
@SuppressWarnings("NullAway")
|
||||
@Override
|
||||
public Class<? extends ConfigurableEnvironment> getEnvironmentType(WebApplicationType webApplicationType) {
|
||||
public @Nullable Class<? extends ConfigurableEnvironment> getEnvironmentType(
|
||||
@Nullable WebApplicationType webApplicationType) {
|
||||
return getFromSpringFactories(webApplicationType, ApplicationContextFactory::getEnvironmentType, null);
|
||||
}
|
||||
|
||||
// Method reference is not detected with correct nullability
|
||||
@SuppressWarnings("NullAway")
|
||||
@Override
|
||||
public ConfigurableEnvironment createEnvironment(WebApplicationType webApplicationType) {
|
||||
public @Nullable ConfigurableEnvironment createEnvironment(@Nullable WebApplicationType webApplicationType) {
|
||||
return getFromSpringFactories(webApplicationType, ApplicationContextFactory::createEnvironment, null);
|
||||
}
|
||||
|
||||
// Method reference is not detected with correct nullability
|
||||
@SuppressWarnings("NullAway")
|
||||
@Override
|
||||
public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
|
||||
public ConfigurableApplicationContext create(@Nullable WebApplicationType webApplicationType) {
|
||||
try {
|
||||
return getFromSpringFactories(webApplicationType, ApplicationContextFactory::create,
|
||||
this::createDefaultApplicationContext);
|
||||
@@ -63,8 +73,10 @@ class DefaultApplicationContextFactory implements ApplicationContextFactory {
|
||||
return new GenericApplicationContext();
|
||||
}
|
||||
|
||||
private <T> T getFromSpringFactories(WebApplicationType webApplicationType,
|
||||
BiFunction<ApplicationContextFactory, WebApplicationType, T> action, Supplier<T> defaultResult) {
|
||||
@Contract("_, _, !null -> !null")
|
||||
private <T> @Nullable T getFromSpringFactories(@Nullable WebApplicationType webApplicationType,
|
||||
BiFunction<ApplicationContextFactory, @Nullable WebApplicationType, @Nullable T> action,
|
||||
@Nullable Supplier<T> defaultResult) {
|
||||
for (ApplicationContextFactory candidate : SpringFactoriesLoader.loadFactories(ApplicationContextFactory.class,
|
||||
getClass().getClassLoader())) {
|
||||
T result = action.apply(candidate, webApplicationType);
|
||||
|
||||
+13
-6
@@ -20,6 +20,8 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
@@ -72,7 +74,7 @@ public class DefaultBootstrapContext implements ConfigurableBootstrapContext {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> InstanceSupplier<T> getRegisteredInstanceSupplier(Class<T> type) {
|
||||
public <T> @Nullable InstanceSupplier<T> getRegisteredInstanceSupplier(Class<T> type) {
|
||||
synchronized (this.instanceSuppliers) {
|
||||
return (InstanceSupplier<T>) this.instanceSuppliers.get(type);
|
||||
}
|
||||
@@ -84,17 +86,18 @@ public class DefaultBootstrapContext implements ConfigurableBootstrapContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T get(Class<T> type) throws IllegalStateException {
|
||||
public <T> @Nullable T get(Class<T> type) throws IllegalStateException {
|
||||
return getOrElseThrow(type, () -> new IllegalStateException(type.getName() + " has not been registered"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getOrElse(Class<T> type, T other) {
|
||||
@SuppressWarnings("NullAway") // Doesn't detect lambda with correct nullability
|
||||
public <T> @Nullable T getOrElse(Class<T> type, @Nullable T other) {
|
||||
return getOrElseSupply(type, () -> other);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getOrElseSupply(Class<T> type, Supplier<T> other) {
|
||||
public <T> @Nullable T getOrElseSupply(Class<T> type, Supplier<@Nullable T> other) {
|
||||
synchronized (this.instanceSuppliers) {
|
||||
InstanceSupplier<?> instanceSupplier = this.instanceSuppliers.get(type);
|
||||
return (instanceSupplier != null) ? getInstance(type, instanceSupplier) : other.get();
|
||||
@@ -102,7 +105,8 @@ public class DefaultBootstrapContext implements ConfigurableBootstrapContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, X extends Throwable> T getOrElseThrow(Class<T> type, Supplier<? extends X> exceptionSupplier) throws X {
|
||||
public <T, X extends Throwable> @Nullable T getOrElseThrow(Class<T> type, Supplier<? extends X> exceptionSupplier)
|
||||
throws X {
|
||||
synchronized (this.instanceSuppliers) {
|
||||
InstanceSupplier<?> instanceSupplier = this.instanceSuppliers.get(type);
|
||||
if (instanceSupplier == null) {
|
||||
@@ -113,10 +117,13 @@ public class DefaultBootstrapContext implements ConfigurableBootstrapContext {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T getInstance(Class<T> type, InstanceSupplier<?> instanceSupplier) {
|
||||
private <T> @Nullable T getInstance(Class<T> type, InstanceSupplier<?> instanceSupplier) {
|
||||
T instance = (T) this.instances.get(type);
|
||||
if (instance == null) {
|
||||
instance = (T) instanceSupplier.get(this);
|
||||
if (instance == null) {
|
||||
return null;
|
||||
}
|
||||
if (instanceSupplier.getScope() == Scope.SINGLETON) {
|
||||
this.instances.put(type, instance);
|
||||
}
|
||||
|
||||
+5
-2
@@ -20,6 +20,8 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
@@ -56,7 +58,7 @@ public class DefaultPropertiesPropertySource extends MapPropertySource {
|
||||
* @param propertySource the property source to check
|
||||
* @return {@code true} if the name matches
|
||||
*/
|
||||
public static boolean hasMatchingName(PropertySource<?> propertySource) {
|
||||
public static boolean hasMatchingName(@Nullable PropertySource<?> propertySource) {
|
||||
return (propertySource != null) && propertySource.getName().equals(NAME);
|
||||
}
|
||||
|
||||
@@ -67,7 +69,8 @@ public class DefaultPropertiesPropertySource extends MapPropertySource {
|
||||
* @param action the action used to consume the
|
||||
* {@link DefaultPropertiesPropertySource}
|
||||
*/
|
||||
public static void ifNotEmpty(Map<String, Object> source, Consumer<DefaultPropertiesPropertySource> action) {
|
||||
public static void ifNotEmpty(Map<String, Object> source,
|
||||
@Nullable Consumer<DefaultPropertiesPropertySource> action) {
|
||||
if (!CollectionUtils.isEmpty(source) && action != null) {
|
||||
action.accept(new DefaultPropertiesPropertySource(source));
|
||||
}
|
||||
|
||||
+4
-2
@@ -19,6 +19,8 @@ package org.springframework.boot;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||
@@ -84,7 +86,7 @@ public final class LazyInitializationBeanFactoryPostProcessor implements BeanFac
|
||||
}
|
||||
}
|
||||
|
||||
private Class<?> getBeanType(ConfigurableListableBeanFactory beanFactory, String beanName) {
|
||||
private @Nullable Class<?> getBeanType(ConfigurableListableBeanFactory beanFactory, String beanName) {
|
||||
try {
|
||||
return beanFactory.getType(beanName, false);
|
||||
}
|
||||
@@ -94,7 +96,7 @@ public final class LazyInitializationBeanFactoryPostProcessor implements BeanFac
|
||||
}
|
||||
|
||||
private boolean isExcluded(Collection<LazyInitializationExcludeFilter> filters, String beanName,
|
||||
AbstractBeanDefinition beanDefinition, Class<?> beanType) {
|
||||
AbstractBeanDefinition beanDefinition, @Nullable Class<?> beanType) {
|
||||
if (beanType != null) {
|
||||
for (LazyInitializationExcludeFilter filter : filters) {
|
||||
if (filter.isExcluded(beanName, beanDefinition, beanType)) {
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.ansi.AnsiPropertySource;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
@@ -64,7 +65,7 @@ public class ResourceBanner implements Banner {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printBanner(Environment environment, Class<?> sourceClass, PrintStream out) {
|
||||
public void printBanner(Environment environment, @Nullable Class<?> sourceClass, PrintStream out) {
|
||||
try (InputStream input = this.resource.getInputStream()) {
|
||||
String banner = StreamUtils.copyToString(input,
|
||||
environment.getProperty("spring.banner.charset", Charset.class, StandardCharsets.UTF_8));
|
||||
@@ -86,32 +87,32 @@ public class ResourceBanner implements Banner {
|
||||
* @param sourceClass the source class
|
||||
* @return a mutable list of property resolvers
|
||||
*/
|
||||
protected List<PropertyResolver> getPropertyResolvers(Environment environment, Class<?> sourceClass) {
|
||||
protected List<PropertyResolver> getPropertyResolvers(Environment environment, @Nullable Class<?> sourceClass) {
|
||||
List<PropertyResolver> resolvers = new ArrayList<>();
|
||||
resolvers.add(new PropertySourcesPropertyResolver(createNullDefaultSources(environment, sourceClass)));
|
||||
resolvers.add(new PropertySourcesPropertyResolver(createEmptyDefaultSources(environment, sourceClass)));
|
||||
return resolvers;
|
||||
}
|
||||
|
||||
private MutablePropertySources createNullDefaultSources(Environment environment, Class<?> sourceClass) {
|
||||
private MutablePropertySources createNullDefaultSources(Environment environment, @Nullable Class<?> sourceClass) {
|
||||
MutablePropertySources nullDefaultSources = new MutablePropertySources();
|
||||
if (environment instanceof ConfigurableEnvironment configurableEnvironment) {
|
||||
configurableEnvironment.getPropertySources().forEach(nullDefaultSources::addLast);
|
||||
}
|
||||
nullDefaultSources.addLast(getTitleSource(sourceClass, null));
|
||||
nullDefaultSources.addLast(getAnsiSource());
|
||||
nullDefaultSources.addLast(getVersionSource(sourceClass, environment, null));
|
||||
nullDefaultSources.addLast(getVersionSource(environment, null));
|
||||
return nullDefaultSources;
|
||||
}
|
||||
|
||||
private MutablePropertySources createEmptyDefaultSources(Environment environment, Class<?> sourceClass) {
|
||||
private MutablePropertySources createEmptyDefaultSources(Environment environment, @Nullable Class<?> sourceClass) {
|
||||
MutablePropertySources emptyDefaultSources = new MutablePropertySources();
|
||||
emptyDefaultSources.addLast(getTitleSource(sourceClass, ""));
|
||||
emptyDefaultSources.addLast(getVersionSource(sourceClass, environment, ""));
|
||||
emptyDefaultSources.addLast(getVersionSource(environment, ""));
|
||||
return emptyDefaultSources;
|
||||
}
|
||||
|
||||
private MapPropertySource getTitleSource(Class<?> sourceClass, String defaultValue) {
|
||||
private MapPropertySource getTitleSource(@Nullable Class<?> sourceClass, @Nullable String defaultValue) {
|
||||
String applicationTitle = getApplicationTitle(sourceClass);
|
||||
Map<String, Object> titleMap = Collections.singletonMap("application.title",
|
||||
(applicationTitle != null) ? applicationTitle : defaultValue);
|
||||
@@ -124,7 +125,7 @@ public class ResourceBanner implements Banner {
|
||||
* @param sourceClass the source class
|
||||
* @return the application title
|
||||
*/
|
||||
protected String getApplicationTitle(Class<?> sourceClass) {
|
||||
protected @Nullable String getApplicationTitle(@Nullable Class<?> sourceClass) {
|
||||
Package sourcePackage = (sourceClass != null) ? sourceClass.getPackage() : null;
|
||||
return (sourcePackage != null) ? sourcePackage.getImplementationTitle() : null;
|
||||
}
|
||||
@@ -133,11 +134,11 @@ public class ResourceBanner implements Banner {
|
||||
return new AnsiPropertySource("ansi", true);
|
||||
}
|
||||
|
||||
private MapPropertySource getVersionSource(Class<?> sourceClass, Environment environment, String defaultValue) {
|
||||
return new MapPropertySource("version", getVersionsMap(sourceClass, environment, defaultValue));
|
||||
private MapPropertySource getVersionSource(Environment environment, @Nullable String defaultValue) {
|
||||
return new MapPropertySource("version", getVersionsMap(environment, defaultValue));
|
||||
}
|
||||
|
||||
private Map<String, Object> getVersionsMap(Class<?> sourceClass, Environment environment, String defaultValue) {
|
||||
private Map<String, Object> getVersionsMap(Environment environment, @Nullable String defaultValue) {
|
||||
String appVersion = getApplicationVersion(environment);
|
||||
String bootVersion = getBootVersion();
|
||||
Map<String, Object> versions = new HashMap<>();
|
||||
@@ -148,7 +149,7 @@ public class ResourceBanner implements Banner {
|
||||
return versions;
|
||||
}
|
||||
|
||||
private String getApplicationVersion(Environment environment) {
|
||||
private @Nullable String getApplicationVersion(Environment environment) {
|
||||
return environment.getProperty("spring.application.version");
|
||||
}
|
||||
|
||||
@@ -156,7 +157,7 @@ public class ResourceBanner implements Banner {
|
||||
return SpringBootVersion.getVersion();
|
||||
}
|
||||
|
||||
private String getVersionString(String version, boolean format, String fallback) {
|
||||
private @Nullable String getVersionString(@Nullable String version, boolean format, @Nullable String fallback) {
|
||||
if (version == null) {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ import java.util.stream.Stream;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.crac.management.CRaCMXBean;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.aot.AotDetector;
|
||||
import org.springframework.beans.BeansException;
|
||||
@@ -204,27 +205,27 @@ public class SpringApplication {
|
||||
|
||||
private final Set<Class<?>> primarySources;
|
||||
|
||||
private Class<?> mainApplicationClass;
|
||||
private @Nullable Class<?> mainApplicationClass;
|
||||
|
||||
private boolean addCommandLineProperties = true;
|
||||
|
||||
private boolean addConversionService = true;
|
||||
|
||||
private Banner banner;
|
||||
private @Nullable Banner banner;
|
||||
|
||||
private ResourceLoader resourceLoader;
|
||||
private @Nullable ResourceLoader resourceLoader;
|
||||
|
||||
private BeanNameGenerator beanNameGenerator;
|
||||
private @Nullable BeanNameGenerator beanNameGenerator;
|
||||
|
||||
private ConfigurableEnvironment environment;
|
||||
private @Nullable ConfigurableEnvironment environment;
|
||||
|
||||
private boolean headless = true;
|
||||
|
||||
private List<ApplicationContextInitializer<?>> initializers;
|
||||
private List<ApplicationContextInitializer<?>> initializers = new ArrayList<>();
|
||||
|
||||
private List<ApplicationListener<?>> listeners;
|
||||
private List<ApplicationListener<?>> listeners = new ArrayList<>();
|
||||
|
||||
private Map<String, Object> defaultProperties;
|
||||
private @Nullable Map<String, Object> defaultProperties;
|
||||
|
||||
private final List<BootstrapRegistryInitializer> bootstrapRegistryInitializers;
|
||||
|
||||
@@ -232,7 +233,7 @@ public class SpringApplication {
|
||||
|
||||
private boolean isCustomEnvironment;
|
||||
|
||||
private String environmentPrefix;
|
||||
private @Nullable String environmentPrefix;
|
||||
|
||||
private ApplicationContextFactory applicationContextFactory = ApplicationContextFactory.DEFAULT;
|
||||
|
||||
@@ -265,7 +266,7 @@ public class SpringApplication {
|
||||
* @see #setSources(Set)
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
|
||||
public SpringApplication(@Nullable ResourceLoader resourceLoader, Class<?>... primarySources) {
|
||||
this.resourceLoader = resourceLoader;
|
||||
Assert.notNull(primarySources, "'primarySources' must not be null");
|
||||
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
|
||||
@@ -277,7 +278,7 @@ public class SpringApplication {
|
||||
this.mainApplicationClass = deduceMainApplicationClass();
|
||||
}
|
||||
|
||||
private Class<?> deduceMainApplicationClass() {
|
||||
private @Nullable Class<?> deduceMainApplicationClass() {
|
||||
return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE)
|
||||
.walk(this::findMainClass)
|
||||
.orElse(null);
|
||||
@@ -314,11 +315,11 @@ public class SpringApplication {
|
||||
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
|
||||
refreshContext(context);
|
||||
afterRefresh(context, applicationArguments);
|
||||
startup.started();
|
||||
Duration timeTakenToStarted = startup.started();
|
||||
if (this.properties.isLogStartupInfo()) {
|
||||
new StartupInfoLogger(this.mainApplicationClass, environment).logStarted(getApplicationLog(), startup);
|
||||
}
|
||||
listeners.started(context, startup.timeTakenToStarted());
|
||||
listeners.started(context, timeTakenToStarted);
|
||||
callRunners(context, applicationArguments);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
@@ -373,7 +374,7 @@ public class SpringApplication {
|
||||
|
||||
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
|
||||
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
|
||||
ApplicationArguments applicationArguments, Banner printedBanner) {
|
||||
ApplicationArguments applicationArguments, @Nullable Banner printedBanner) {
|
||||
context.setEnvironment(environment);
|
||||
postProcessApplicationContext(context);
|
||||
addAotGeneratedInitializerIfNecessary(this.initializers);
|
||||
@@ -417,6 +418,7 @@ public class SpringApplication {
|
||||
List<ApplicationContextInitializer<?>> aotInitializers = new ArrayList<>(
|
||||
initializers.stream().filter(AotApplicationContextInitializer.class::isInstance).toList());
|
||||
if (aotInitializers.isEmpty()) {
|
||||
Assert.state(this.mainApplicationClass != null, "No application main class found");
|
||||
String initializerClassName = this.mainApplicationClass.getName() + "__ApplicationContextInitializer";
|
||||
if (!ClassUtils.isPresent(initializerClassName, getClassLoader())) {
|
||||
throw new AotInitializerNotFoundException(this.mainApplicationClass, initializerClassName);
|
||||
@@ -458,7 +460,7 @@ public class SpringApplication {
|
||||
return getSpringFactoriesInstances(type, null);
|
||||
}
|
||||
|
||||
private <T> List<T> getSpringFactoriesInstances(Class<T> type, ArgumentResolver argumentResolver) {
|
||||
private <T> List<T> getSpringFactoriesInstances(Class<T> type, @Nullable ArgumentResolver argumentResolver) {
|
||||
return SpringFactoriesLoader.forDefaultResourceLocation(getClassLoader()).load(type, argumentResolver);
|
||||
}
|
||||
|
||||
@@ -507,8 +509,8 @@ public class SpringApplication {
|
||||
}
|
||||
if (this.addCommandLineProperties && args.length > 0) {
|
||||
String name = CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME;
|
||||
if (sources.contains(name)) {
|
||||
PropertySource<?> source = sources.get(name);
|
||||
PropertySource<?> source = sources.get(name);
|
||||
if (source != null) {
|
||||
CompositePropertySource composite = new CompositePropertySource(name);
|
||||
composite
|
||||
.addPropertySource(new SimpleCommandLinePropertySource("springApplicationCommandLineArgs", args));
|
||||
@@ -546,7 +548,7 @@ public class SpringApplication {
|
||||
}
|
||||
}
|
||||
|
||||
private Banner printBanner(ConfigurableEnvironment environment) {
|
||||
private @Nullable Banner printBanner(ConfigurableEnvironment environment) {
|
||||
if (this.properties.getBannerMode(environment) == Banner.Mode.OFF) {
|
||||
return null;
|
||||
}
|
||||
@@ -604,6 +606,8 @@ public class SpringApplication {
|
||||
for (ApplicationContextInitializer initializer : getInitializers()) {
|
||||
Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
|
||||
ApplicationContextInitializer.class);
|
||||
Assert.state(requiredType != null,
|
||||
() -> "No generic type found for initializr of type " + initializer.getClass());
|
||||
Assert.state(requiredType.isInstance(context), "Unable to call initializer");
|
||||
initializer.initialize(context);
|
||||
}
|
||||
@@ -685,9 +689,9 @@ public class SpringApplication {
|
||||
/**
|
||||
* The ResourceLoader that will be used in the ApplicationContext.
|
||||
* @return the resourceLoader the resource loader that will be used in the
|
||||
* ApplicationContext (or null if the default)
|
||||
* ApplicationContext (or {@code null} if the default)
|
||||
*/
|
||||
public ResourceLoader getResourceLoader() {
|
||||
public @Nullable ResourceLoader getResourceLoader() {
|
||||
return this.resourceLoader;
|
||||
}
|
||||
|
||||
@@ -699,9 +703,13 @@ public class SpringApplication {
|
||||
*/
|
||||
public ClassLoader getClassLoader() {
|
||||
if (this.resourceLoader != null) {
|
||||
return this.resourceLoader.getClassLoader();
|
||||
ClassLoader classLoader = this.resourceLoader.getClassLoader();
|
||||
Assert.state(classLoader != null, "No classloader found");
|
||||
return classLoader;
|
||||
}
|
||||
return ClassUtils.getDefaultClassLoader();
|
||||
ClassLoader classLoader = ClassUtils.getDefaultClassLoader();
|
||||
Assert.state(classLoader != null, "No classloader found");
|
||||
return classLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -781,8 +789,8 @@ public class SpringApplication {
|
||||
.accept((R) runner);
|
||||
}
|
||||
|
||||
private RuntimeException handleRunFailure(ConfigurableApplicationContext context, Throwable exception,
|
||||
SpringApplicationRunListeners listeners) {
|
||||
private RuntimeException handleRunFailure(@Nullable ConfigurableApplicationContext context, Throwable exception,
|
||||
@Nullable SpringApplicationRunListeners listeners) {
|
||||
if (exception instanceof AbandonedRunException abandonedRunException) {
|
||||
return abandonedRunException;
|
||||
}
|
||||
@@ -808,9 +816,11 @@ public class SpringApplication {
|
||||
: new IllegalStateException(exception);
|
||||
}
|
||||
|
||||
private Collection<SpringBootExceptionReporter> getExceptionReporters(ConfigurableApplicationContext context) {
|
||||
private Collection<SpringBootExceptionReporter> getExceptionReporters(
|
||||
@Nullable ConfigurableApplicationContext context) {
|
||||
try {
|
||||
ArgumentResolver argumentResolver = ArgumentResolver.of(ConfigurableApplicationContext.class, context);
|
||||
ArgumentResolver argumentResolver = (context != null)
|
||||
? ArgumentResolver.of(ConfigurableApplicationContext.class, context) : ArgumentResolver.none();
|
||||
return getSpringFactoriesInstances(SpringBootExceptionReporter.class, argumentResolver);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
@@ -857,7 +867,7 @@ public class SpringApplication {
|
||||
}
|
||||
}
|
||||
|
||||
private void handleExitCode(ConfigurableApplicationContext context, Throwable exception) {
|
||||
private void handleExitCode(@Nullable ConfigurableApplicationContext context, Throwable exception) {
|
||||
int exitCode = getExitCodeFromException(context, exception);
|
||||
if (exitCode != 0) {
|
||||
if (context != null) {
|
||||
@@ -870,7 +880,7 @@ public class SpringApplication {
|
||||
}
|
||||
}
|
||||
|
||||
private int getExitCodeFromException(ConfigurableApplicationContext context, Throwable exception) {
|
||||
private int getExitCodeFromException(@Nullable ConfigurableApplicationContext context, Throwable exception) {
|
||||
int exitCode = getExitCodeFromMappedException(context, exception);
|
||||
if (exitCode == 0) {
|
||||
exitCode = getExitCodeFromExitCodeGeneratorException(exception);
|
||||
@@ -878,7 +888,7 @@ public class SpringApplication {
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
private int getExitCodeFromMappedException(ConfigurableApplicationContext context, Throwable exception) {
|
||||
private int getExitCodeFromMappedException(@Nullable ConfigurableApplicationContext context, Throwable exception) {
|
||||
if (context == null || !context.isActive()) {
|
||||
return 0;
|
||||
}
|
||||
@@ -888,7 +898,7 @@ public class SpringApplication {
|
||||
return generators.getExitCode();
|
||||
}
|
||||
|
||||
private int getExitCodeFromExitCodeGeneratorException(Throwable exception) {
|
||||
private int getExitCodeFromExitCodeGeneratorException(@Nullable Throwable exception) {
|
||||
if (exception == null) {
|
||||
return 0;
|
||||
}
|
||||
@@ -898,7 +908,7 @@ public class SpringApplication {
|
||||
return getExitCodeFromExitCodeGeneratorException(exception.getCause());
|
||||
}
|
||||
|
||||
SpringBootExceptionHandler getSpringBootExceptionHandler() {
|
||||
@Nullable SpringBootExceptionHandler getSpringBootExceptionHandler() {
|
||||
if (isMainThread(Thread.currentThread())) {
|
||||
return SpringBootExceptionHandler.forCurrentThread();
|
||||
}
|
||||
@@ -914,7 +924,7 @@ public class SpringApplication {
|
||||
* Returns the main application class that has been deduced or explicitly configured.
|
||||
* @return the main application class or {@code null}
|
||||
*/
|
||||
public Class<?> getMainApplicationClass() {
|
||||
public @Nullable Class<?> getMainApplicationClass() {
|
||||
return this.mainApplicationClass;
|
||||
}
|
||||
|
||||
@@ -924,7 +934,7 @@ public class SpringApplication {
|
||||
* Can be set to {@code null} if there is no explicit application class.
|
||||
* @param mainApplicationClass the mainApplicationClass to set or {@code null}
|
||||
*/
|
||||
public void setMainApplicationClass(Class<?> mainApplicationClass) {
|
||||
public void setMainApplicationClass(@Nullable Class<?> mainApplicationClass) {
|
||||
this.mainApplicationClass = mainApplicationClass;
|
||||
}
|
||||
|
||||
@@ -933,7 +943,7 @@ public class SpringApplication {
|
||||
* @return the type of web application
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public WebApplicationType getWebApplicationType() {
|
||||
public @Nullable WebApplicationType getWebApplicationType() {
|
||||
return this.properties.getWebApplicationType();
|
||||
}
|
||||
|
||||
@@ -1107,7 +1117,7 @@ public class SpringApplication {
|
||||
* context.
|
||||
* @param environment the environment
|
||||
*/
|
||||
public void setEnvironment(ConfigurableEnvironment environment) {
|
||||
public void setEnvironment(@Nullable ConfigurableEnvironment environment) {
|
||||
this.isCustomEnvironment = true;
|
||||
this.environment = environment;
|
||||
}
|
||||
@@ -1191,7 +1201,7 @@ public class SpringApplication {
|
||||
* @return the environment property prefix
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public String getEnvironmentPrefix() {
|
||||
public @Nullable String getEnvironmentPrefix() {
|
||||
return this.environmentPrefix;
|
||||
}
|
||||
|
||||
@@ -1213,7 +1223,7 @@ public class SpringApplication {
|
||||
* @param applicationContextFactory the factory for the context
|
||||
* @since 2.4.0
|
||||
*/
|
||||
public void setApplicationContextFactory(ApplicationContextFactory applicationContextFactory) {
|
||||
public void setApplicationContextFactory(@Nullable ApplicationContextFactory applicationContextFactory) {
|
||||
this.applicationContextFactory = (applicationContextFactory != null) ? applicationContextFactory
|
||||
: ApplicationContextFactory.DEFAULT;
|
||||
}
|
||||
@@ -1424,7 +1434,7 @@ public class SpringApplication {
|
||||
public static void withHook(SpringApplicationHook hook, Runnable action) {
|
||||
withHook(hook, () -> {
|
||||
action.run();
|
||||
return null;
|
||||
return Void.class;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1598,7 +1608,7 @@ public class SpringApplication {
|
||||
*/
|
||||
public static class AbandonedRunException extends RuntimeException {
|
||||
|
||||
private final ConfigurableApplicationContext applicationContext;
|
||||
private final @Nullable ConfigurableApplicationContext applicationContext;
|
||||
|
||||
/**
|
||||
* Create a new {@link AbandonedRunException} instance.
|
||||
@@ -1613,7 +1623,7 @@ public class SpringApplication {
|
||||
* @param applicationContext the application context that was available when the
|
||||
* run was abandoned
|
||||
*/
|
||||
public AbandonedRunException(ConfigurableApplicationContext applicationContext) {
|
||||
public AbandonedRunException(@Nullable ConfigurableApplicationContext applicationContext) {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
@@ -1622,7 +1632,7 @@ public class SpringApplication {
|
||||
* {@code null} if no context was available.
|
||||
* @return the application context
|
||||
*/
|
||||
public ConfigurableApplicationContext getApplicationContext() {
|
||||
public @Nullable ConfigurableApplicationContext getApplicationContext() {
|
||||
return this.applicationContext;
|
||||
}
|
||||
|
||||
@@ -1642,7 +1652,7 @@ public class SpringApplication {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpringApplicationRunListener getRunListener(SpringApplication springApplication) {
|
||||
public @Nullable SpringApplicationRunListener getRunListener(SpringApplication springApplication) {
|
||||
return this.used.compareAndSet(false, true) ? this.delegate.getRunListener(springApplication) : null;
|
||||
}
|
||||
|
||||
@@ -1699,11 +1709,11 @@ public class SpringApplication {
|
||||
*/
|
||||
abstract static class Startup {
|
||||
|
||||
private Duration timeTakenToStarted;
|
||||
private @Nullable Duration timeTakenToStarted;
|
||||
|
||||
protected abstract long startTime();
|
||||
|
||||
protected abstract Long processUptime();
|
||||
protected abstract @Nullable Long processUptime();
|
||||
|
||||
protected abstract String action();
|
||||
|
||||
@@ -1714,6 +1724,8 @@ public class SpringApplication {
|
||||
}
|
||||
|
||||
Duration timeTakenToStarted() {
|
||||
Assert.state(this.timeTakenToStarted != null,
|
||||
"timeTakenToStarted is not set. Make sure to call started() before this method");
|
||||
return this.timeTakenToStarted;
|
||||
}
|
||||
|
||||
@@ -1744,7 +1756,7 @@ public class SpringApplication {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Long processUptime() {
|
||||
protected @Nullable Long processUptime() {
|
||||
try {
|
||||
return ManagementFactory.getRuntimeMXBean().getUptime();
|
||||
}
|
||||
@@ -1794,7 +1806,7 @@ public class SpringApplication {
|
||||
* {@link OrderSourceProvider} used to obtain factory method and target type order
|
||||
* sources. Based on internal {@link DefaultListableBeanFactory} code.
|
||||
*/
|
||||
private class FactoryAwareOrderSourceProvider implements OrderSourceProvider {
|
||||
private static class FactoryAwareOrderSourceProvider implements OrderSourceProvider {
|
||||
|
||||
private final ConfigurableBeanFactory beanFactory;
|
||||
|
||||
@@ -1806,12 +1818,12 @@ public class SpringApplication {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getOrderSource(Object obj) {
|
||||
public @Nullable Object getOrderSource(Object obj) {
|
||||
String beanName = this.instancesToBeanNames.get(obj);
|
||||
return (beanName != null) ? getOrderSource(beanName, obj.getClass()) : null;
|
||||
}
|
||||
|
||||
private Object getOrderSource(String beanName, Class<?> instanceType) {
|
||||
private @Nullable Object getOrderSource(String beanName, Class<?> instanceType) {
|
||||
try {
|
||||
RootBeanDefinition beanDefinition = (RootBeanDefinition) this.beanFactory
|
||||
.getMergedBeanDefinition(beanName);
|
||||
|
||||
+3
-2
@@ -59,7 +59,8 @@ public class SpringApplicationAotProcessor extends ContextAotProcessor {
|
||||
protected GenericApplicationContext prepareApplicationContext(Class<?> application) {
|
||||
return new AotProcessorHook(application).run(() -> {
|
||||
Method mainMethod = application.getMethod("main", String[].class);
|
||||
return ReflectionUtils.invokeMethod(mainMethod, null, new Object[] { this.applicationArgs });
|
||||
ReflectionUtils.invokeMethod(mainMethod, null, new Object[] { this.applicationArgs });
|
||||
return Void.class;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -112,7 +113,7 @@ public class SpringApplicationAotProcessor extends ContextAotProcessor {
|
||||
ApplicationContext context = ex.getApplicationContext();
|
||||
Assert.state(context instanceof GenericApplicationContext,
|
||||
() -> "AOT processing requires a GenericApplicationContext but got a "
|
||||
+ context.getClass().getName());
|
||||
+ ((context != null) ? context.getClass().getName() : "null"));
|
||||
return (GenericApplicationContext) context;
|
||||
}
|
||||
throw new IllegalStateException(
|
||||
|
||||
+12
-11
@@ -23,6 +23,7 @@ import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.aot.hint.RuntimeHintsRegistrar;
|
||||
@@ -45,14 +46,14 @@ class SpringApplicationBannerPrinter {
|
||||
|
||||
private final ResourceLoader resourceLoader;
|
||||
|
||||
private final Banner fallbackBanner;
|
||||
private final @Nullable Banner fallbackBanner;
|
||||
|
||||
SpringApplicationBannerPrinter(ResourceLoader resourceLoader, Banner fallbackBanner) {
|
||||
SpringApplicationBannerPrinter(ResourceLoader resourceLoader, @Nullable Banner fallbackBanner) {
|
||||
this.resourceLoader = resourceLoader;
|
||||
this.fallbackBanner = fallbackBanner;
|
||||
}
|
||||
|
||||
Banner print(Environment environment, Class<?> sourceClass, Log logger) {
|
||||
Banner print(Environment environment, @Nullable Class<?> sourceClass, Log logger) {
|
||||
Banner banner = getBanner(environment);
|
||||
try {
|
||||
logger.info(createStringFromBanner(banner, environment, sourceClass));
|
||||
@@ -63,7 +64,7 @@ class SpringApplicationBannerPrinter {
|
||||
return new PrintedBanner(banner, sourceClass);
|
||||
}
|
||||
|
||||
Banner print(Environment environment, Class<?> sourceClass, PrintStream out) {
|
||||
Banner print(Environment environment, @Nullable Class<?> sourceClass, PrintStream out) {
|
||||
Banner banner = getBanner(environment);
|
||||
banner.printBanner(environment, sourceClass, out);
|
||||
return new PrintedBanner(banner, sourceClass);
|
||||
@@ -80,7 +81,7 @@ class SpringApplicationBannerPrinter {
|
||||
return DEFAULT_BANNER;
|
||||
}
|
||||
|
||||
private Banner getTextBanner(Environment environment) {
|
||||
private @Nullable Banner getTextBanner(Environment environment) {
|
||||
String location = environment.getProperty(BANNER_LOCATION_PROPERTY, DEFAULT_BANNER_LOCATION);
|
||||
Resource resource = this.resourceLoader.getResource(location);
|
||||
try {
|
||||
@@ -94,8 +95,8 @@ class SpringApplicationBannerPrinter {
|
||||
return null;
|
||||
}
|
||||
|
||||
private String createStringFromBanner(Banner banner, Environment environment, Class<?> mainApplicationClass)
|
||||
throws UnsupportedEncodingException {
|
||||
private String createStringFromBanner(Banner banner, Environment environment,
|
||||
@Nullable Class<?> mainApplicationClass) throws UnsupportedEncodingException {
|
||||
String charset = environment.getProperty("spring.banner.charset", StandardCharsets.UTF_8.name());
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
try (PrintStream out = new PrintStream(byteArrayOutputStream, false, charset)) {
|
||||
@@ -112,15 +113,15 @@ class SpringApplicationBannerPrinter {
|
||||
|
||||
private final Banner banner;
|
||||
|
||||
private final Class<?> sourceClass;
|
||||
private final @Nullable Class<?> sourceClass;
|
||||
|
||||
PrintedBanner(Banner banner, Class<?> sourceClass) {
|
||||
PrintedBanner(Banner banner, @Nullable Class<?> sourceClass) {
|
||||
this.banner = banner;
|
||||
this.sourceClass = sourceClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printBanner(Environment environment, Class<?> sourceClass, PrintStream out) {
|
||||
public void printBanner(Environment environment, @Nullable Class<?> sourceClass, PrintStream out) {
|
||||
sourceClass = (sourceClass != null) ? sourceClass : this.sourceClass;
|
||||
this.banner.printBanner(environment, sourceClass, out);
|
||||
}
|
||||
@@ -130,7 +131,7 @@ class SpringApplicationBannerPrinter {
|
||||
static class SpringApplicationBannerPrinterRuntimeHints implements RuntimeHintsRegistrar {
|
||||
|
||||
@Override
|
||||
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
|
||||
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
|
||||
hints.resources().registerPattern(DEFAULT_BANNER_LOCATION);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.boot;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Low-level hook that can be used to attach a {@link SpringApplicationRunListener} to a
|
||||
* {@link SpringApplication} in order to observe or modify its behavior. Hooks are managed
|
||||
@@ -34,8 +36,8 @@ public interface SpringApplicationHook {
|
||||
* Return the {@link SpringApplicationRunListener} that should be hooked into the
|
||||
* given {@link SpringApplication}.
|
||||
* @param springApplication the source {@link SpringApplication} instance
|
||||
* @return the {@link SpringApplicationRunListener} to attach
|
||||
* @return the {@link SpringApplicationRunListener} to attach or {@code null}
|
||||
*/
|
||||
SpringApplicationRunListener getRunListener(SpringApplication springApplication);
|
||||
@Nullable SpringApplicationRunListener getRunListener(SpringApplication springApplication);
|
||||
|
||||
}
|
||||
|
||||
+5
-3
@@ -18,6 +18,8 @@ package org.springframework.boot;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
@@ -80,7 +82,7 @@ public interface SpringApplicationRunListener {
|
||||
* @param timeTaken the time taken to start the application or {@code null} if unknown
|
||||
* @since 2.6.0
|
||||
*/
|
||||
default void started(ConfigurableApplicationContext context, Duration timeTaken) {
|
||||
default void started(ConfigurableApplicationContext context, @Nullable Duration timeTaken) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,7 +94,7 @@ public interface SpringApplicationRunListener {
|
||||
* unknown
|
||||
* @since 2.6.0
|
||||
*/
|
||||
default void ready(ConfigurableApplicationContext context, Duration timeTaken) {
|
||||
default void ready(ConfigurableApplicationContext context, @Nullable Duration timeTaken) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,7 +104,7 @@ public interface SpringApplicationRunListener {
|
||||
* @param exception the failure
|
||||
* @since 2.0.0
|
||||
*/
|
||||
default void failed(ConfigurableApplicationContext context, Throwable exception) {
|
||||
default void failed(@Nullable ConfigurableApplicationContext context, Throwable exception) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+10
-6
@@ -21,6 +21,7 @@ import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
@@ -50,7 +51,7 @@ class SpringApplicationRunListeners {
|
||||
this.applicationStartup = applicationStartup;
|
||||
}
|
||||
|
||||
void starting(ConfigurableBootstrapContext bootstrapContext, Class<?> mainApplicationClass) {
|
||||
void starting(ConfigurableBootstrapContext bootstrapContext, @Nullable Class<?> mainApplicationClass) {
|
||||
doWithListeners("spring.boot.application.starting", (listener) -> listener.starting(bootstrapContext),
|
||||
(step) -> {
|
||||
if (mainApplicationClass != null) {
|
||||
@@ -80,16 +81,19 @@ class SpringApplicationRunListeners {
|
||||
doWithListeners("spring.boot.application.ready", (listener) -> listener.ready(context, timeTaken));
|
||||
}
|
||||
|
||||
void failed(ConfigurableApplicationContext context, Throwable exception) {
|
||||
void failed(@Nullable ConfigurableApplicationContext context, Throwable exception) {
|
||||
doWithListeners("spring.boot.application.failed",
|
||||
(listener) -> callFailedListener(listener, context, exception), (step) -> {
|
||||
step.tag("exception", exception.getClass().toString());
|
||||
step.tag("message", exception.getMessage());
|
||||
String message = exception.getMessage();
|
||||
if (message != null) {
|
||||
step.tag("message", message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void callFailedListener(SpringApplicationRunListener listener, ConfigurableApplicationContext context,
|
||||
Throwable exception) {
|
||||
private void callFailedListener(SpringApplicationRunListener listener,
|
||||
@Nullable ConfigurableApplicationContext context, Throwable exception) {
|
||||
try {
|
||||
listener.failed(context, exception);
|
||||
}
|
||||
@@ -113,7 +117,7 @@ class SpringApplicationRunListeners {
|
||||
}
|
||||
|
||||
private void doWithListeners(String stepName, Consumer<SpringApplicationRunListener> listenerAction,
|
||||
Consumer<StartupStep> stepAction) {
|
||||
@Nullable Consumer<StartupStep> stepAction) {
|
||||
StartupStep step = this.applicationStartup.start(stepName);
|
||||
this.listeners.forEach(listenerAction);
|
||||
if (stepAction != null) {
|
||||
|
||||
@@ -18,6 +18,8 @@ package org.springframework.boot;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.ansi.AnsiColor;
|
||||
import org.springframework.boot.ansi.AnsiOutput;
|
||||
import org.springframework.boot.ansi.AnsiStyle;
|
||||
@@ -44,7 +46,7 @@ class SpringBootBanner implements Banner {
|
||||
private static final int STRAP_LINE_SIZE = 42;
|
||||
|
||||
@Override
|
||||
public void printBanner(Environment environment, Class<?> sourceClass, PrintStream printStream) {
|
||||
public void printBanner(Environment environment, @Nullable Class<?> sourceClass, PrintStream printStream) {
|
||||
printStream.println();
|
||||
printStream.println(BANNER);
|
||||
String version = String.format(" (v%s)", SpringBootVersion.getVersion());
|
||||
|
||||
+12
-4
@@ -24,6 +24,8 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* {@link UncaughtExceptionHandler} to suppress handling already logged exceptions and
|
||||
* dealing with system exit.
|
||||
@@ -42,13 +44,13 @@ class SpringBootExceptionHandler implements UncaughtExceptionHandler {
|
||||
|
||||
private static final LoggedExceptionHandlerThreadLocal handler = new LoggedExceptionHandlerThreadLocal();
|
||||
|
||||
private final UncaughtExceptionHandler parent;
|
||||
private final @Nullable UncaughtExceptionHandler parent;
|
||||
|
||||
private final List<Throwable> loggedExceptions = new ArrayList<>();
|
||||
|
||||
private int exitCode = 0;
|
||||
|
||||
SpringBootExceptionHandler(UncaughtExceptionHandler parent) {
|
||||
SpringBootExceptionHandler(@Nullable UncaughtExceptionHandler parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@@ -85,7 +87,10 @@ class SpringBootExceptionHandler implements UncaughtExceptionHandler {
|
||||
* @param ex the source exception
|
||||
* @return {@code true} if the exception contains a log configuration message
|
||||
*/
|
||||
private boolean isLogConfigurationMessage(Throwable ex) {
|
||||
private boolean isLogConfigurationMessage(@Nullable Throwable ex) {
|
||||
if (ex == null) {
|
||||
return false;
|
||||
}
|
||||
if (ex instanceof InvocationTargetException) {
|
||||
return isLogConfigurationMessage(ex.getCause());
|
||||
}
|
||||
@@ -100,7 +105,10 @@ class SpringBootExceptionHandler implements UncaughtExceptionHandler {
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isRegistered(Throwable ex) {
|
||||
private boolean isRegistered(@Nullable Throwable ex) {
|
||||
if (ex == null) {
|
||||
return false;
|
||||
}
|
||||
if (this.loggedExceptions.contains(ex)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.springframework.boot;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.aot.AotDetector;
|
||||
import org.springframework.boot.SpringApplication.Startup;
|
||||
@@ -39,11 +40,11 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
class StartupInfoLogger {
|
||||
|
||||
private final Class<?> sourceClass;
|
||||
private final @Nullable Class<?> sourceClass;
|
||||
|
||||
private final Environment environment;
|
||||
|
||||
StartupInfoLogger(Class<?> sourceClass, Environment environment) {
|
||||
StartupInfoLogger(@Nullable Class<?> sourceClass, Environment environment) {
|
||||
this.sourceClass = sourceClass;
|
||||
this.environment = environment;
|
||||
}
|
||||
@@ -153,7 +154,7 @@ class StartupInfoLogger {
|
||||
}
|
||||
}
|
||||
|
||||
private Object callIfPossible(Callable<Object> call) {
|
||||
private @Nullable Object callIfPossible(Callable<Object> call) {
|
||||
try {
|
||||
return call.call();
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.boot;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.aot.hint.RuntimeHintsRegistrar;
|
||||
import org.springframework.aot.hint.TypeReference;
|
||||
@@ -73,7 +75,7 @@ public enum WebApplicationType {
|
||||
static class WebApplicationTypeRuntimeHints implements RuntimeHintsRegistrar {
|
||||
|
||||
@Override
|
||||
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
|
||||
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
|
||||
for (String servletIndicatorClass : SERVLET_INDICATOR_CLASSES) {
|
||||
registerTypeIfPresent(servletIndicatorClass, classLoader, hints);
|
||||
}
|
||||
@@ -82,7 +84,7 @@ public enum WebApplicationType {
|
||||
registerTypeIfPresent(WEBMVC_INDICATOR_CLASS, classLoader, hints);
|
||||
}
|
||||
|
||||
private void registerTypeIfPresent(String typeName, ClassLoader classLoader, RuntimeHints hints) {
|
||||
private void registerTypeIfPresent(String typeName, @Nullable ClassLoader classLoader, RuntimeHints hints) {
|
||||
if (ClassUtils.isPresent(typeName, classLoader)) {
|
||||
hints.reflection().registerType(TypeReference.of(typeName));
|
||||
}
|
||||
|
||||
+3
-1
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.boot.admin;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* An MBean contract to control and monitor a running {@code SpringApplication} over JMX.
|
||||
* Intended for internal use only.
|
||||
@@ -47,7 +49,7 @@ public interface SpringApplicationAdminMXBean {
|
||||
* @param key the property key
|
||||
* @return the property value or {@code null} if it does not exist
|
||||
*/
|
||||
String getProperty(String key);
|
||||
@Nullable String getProperty(String key);
|
||||
|
||||
/**
|
||||
* Shutdown the application.
|
||||
|
||||
+4
-2
@@ -24,6 +24,7 @@ import javax.management.ObjectName;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
@@ -55,6 +56,7 @@ public class SpringApplicationAdminMXBeanRegistrar implements ApplicationContext
|
||||
|
||||
private static final Log logger = LogFactory.getLog(SpringApplicationAdmin.class);
|
||||
|
||||
@SuppressWarnings("NullAway.Init")
|
||||
private ConfigurableApplicationContext applicationContext;
|
||||
|
||||
private Environment environment = new StandardEnvironment();
|
||||
@@ -89,7 +91,7 @@ public class SpringApplicationAdminMXBeanRegistrar implements ApplicationContext
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsSourceType(Class<?> sourceType) {
|
||||
public boolean supportsSourceType(@Nullable Class<?> sourceType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -139,7 +141,7 @@ public class SpringApplicationAdminMXBeanRegistrar implements ApplicationContext
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProperty(String key) {
|
||||
public @Nullable String getProperty(String key) {
|
||||
return SpringApplicationAdminMXBeanRegistrar.this.environment.getProperty(key);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,4 +17,7 @@
|
||||
/**
|
||||
* Administration support for Spring Boot applications.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.boot.admin;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@@ -20,6 +20,8 @@ import java.io.Console;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
@@ -37,9 +39,9 @@ public abstract class AnsiOutput {
|
||||
|
||||
private static Enabled enabled = Enabled.DETECT;
|
||||
|
||||
private static Boolean consoleAvailable;
|
||||
private static @Nullable Boolean consoleAvailable;
|
||||
|
||||
private static Boolean ansiCapable;
|
||||
private static @Nullable Boolean ansiCapable;
|
||||
|
||||
private static final String OPERATING_SYSTEM_NAME = System.getProperty("os.name").toLowerCase(Locale.ENGLISH);
|
||||
|
||||
@@ -71,7 +73,7 @@ public abstract class AnsiOutput {
|
||||
* @param consoleAvailable if the console is known to be available or {@code null} to
|
||||
* use standard detection logic.
|
||||
*/
|
||||
public static void setConsoleAvailable(Boolean consoleAvailable) {
|
||||
public static void setConsoleAvailable(@Nullable Boolean consoleAvailable) {
|
||||
AnsiOutput.consoleAvailable = consoleAvailable;
|
||||
}
|
||||
|
||||
@@ -133,7 +135,7 @@ public abstract class AnsiOutput {
|
||||
}
|
||||
}
|
||||
|
||||
private static void buildDisabled(StringBuilder sb, Object[] elements) {
|
||||
private static void buildDisabled(StringBuilder sb, @Nullable Object[] elements) {
|
||||
for (Object element : elements) {
|
||||
if (!(element instanceof AnsiElement) && element != null) {
|
||||
sb.append(element);
|
||||
|
||||
+6
-4
@@ -23,6 +23,8 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.IntFunction;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.env.PropertyResolver;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -73,7 +75,7 @@ public class AnsiPropertySource extends PropertySource<AnsiElement> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getProperty(String name) {
|
||||
public @Nullable Object getProperty(String name) {
|
||||
if (StringUtils.hasLength(name)) {
|
||||
for (Mapping mapping : MAPPINGS) {
|
||||
String prefix = mapping.getPrefix();
|
||||
@@ -104,7 +106,7 @@ public class AnsiPropertySource extends PropertySource<AnsiElement> {
|
||||
return this.prefix;
|
||||
}
|
||||
|
||||
abstract AnsiElement getElement(String postfix);
|
||||
abstract @Nullable AnsiElement getElement(String postfix);
|
||||
|
||||
}
|
||||
|
||||
@@ -121,7 +123,7 @@ public class AnsiPropertySource extends PropertySource<AnsiElement> {
|
||||
}
|
||||
|
||||
@Override
|
||||
AnsiElement getElement(String postfix) {
|
||||
@Nullable AnsiElement getElement(String postfix) {
|
||||
for (Enum<?> candidate : this.enums) {
|
||||
if (candidate.name().equals(postfix)) {
|
||||
return (AnsiElement) candidate;
|
||||
@@ -145,7 +147,7 @@ public class AnsiPropertySource extends PropertySource<AnsiElement> {
|
||||
}
|
||||
|
||||
@Override
|
||||
AnsiElement getElement(String postfix) {
|
||||
@Nullable AnsiElement getElement(String postfix) {
|
||||
if (containsOnlyDigits(postfix)) {
|
||||
try {
|
||||
return this.factory.apply(Integer.parseInt(postfix));
|
||||
|
||||
@@ -19,4 +19,7 @@
|
||||
*
|
||||
* @see org.springframework.boot.ansi.AnsiOutput
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.boot.ansi;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
+4
-2
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.boot.availability;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
/**
|
||||
@@ -67,7 +69,7 @@ public interface ApplicationAvailability {
|
||||
* published yet
|
||||
* @see #getState(Class, AvailabilityState)
|
||||
*/
|
||||
<S extends AvailabilityState> S getState(Class<S> stateType);
|
||||
<S extends AvailabilityState> @Nullable S getState(Class<S> stateType);
|
||||
|
||||
/**
|
||||
* Return the last {@link AvailabilityChangeEvent} received for a given state type.
|
||||
@@ -76,6 +78,6 @@ public interface ApplicationAvailability {
|
||||
* @return the readiness state or {@code null} if no event of the given type has been
|
||||
* published yet
|
||||
*/
|
||||
<S extends AvailabilityState> AvailabilityChangeEvent<S> getLastChangeEvent(Class<S> stateType);
|
||||
<S extends AvailabilityState> @Nullable AvailabilityChangeEvent<S> getLastChangeEvent(Class<S> stateType);
|
||||
|
||||
}
|
||||
|
||||
+4
-3
@@ -21,6 +21,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
@@ -59,14 +60,14 @@ public class ApplicationAvailabilityBean
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S extends AvailabilityState> S getState(Class<S> stateType) {
|
||||
public <S extends AvailabilityState> @Nullable S getState(Class<S> stateType) {
|
||||
AvailabilityChangeEvent<S> event = getLastChangeEvent(stateType);
|
||||
return (event != null) ? event.getState() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <S extends AvailabilityState> AvailabilityChangeEvent<S> getLastChangeEvent(Class<S> stateType) {
|
||||
public <S extends AvailabilityState> @Nullable AvailabilityChangeEvent<S> getLastChangeEvent(Class<S> stateType) {
|
||||
return (AvailabilityChangeEvent<S>) this.events.get(stateType);
|
||||
}
|
||||
|
||||
@@ -89,7 +90,7 @@ public class ApplicationAvailabilityBean
|
||||
return message;
|
||||
}
|
||||
|
||||
private String getSourceDescription(Object source) {
|
||||
private String getSourceDescription(@Nullable Object source) {
|
||||
if (source == null || source instanceof ApplicationEventPublisher) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -17,4 +17,7 @@
|
||||
/**
|
||||
* Support for describing the availability of Spring Boot applications.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.boot.availability;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
+2
-1
@@ -40,8 +40,9 @@ import org.springframework.util.ObjectUtils;
|
||||
public class ParentContextCloserApplicationListener
|
||||
implements ApplicationListener<ParentContextAvailableEvent>, ApplicationContextAware, Ordered {
|
||||
|
||||
private final int order = Ordered.LOWEST_PRECEDENCE - 10;
|
||||
private static final int order = Ordered.LOWEST_PRECEDENCE - 10;
|
||||
|
||||
@SuppressWarnings("NullAway.Init")
|
||||
private ApplicationContext context;
|
||||
|
||||
@Override
|
||||
|
||||
+18
-11
@@ -27,6 +27,8 @@ import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanNameGenerator;
|
||||
import org.springframework.boot.ApplicationContextFactory;
|
||||
@@ -44,6 +46,7 @@ import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.metrics.ApplicationStartup;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -76,9 +79,9 @@ public class SpringApplicationBuilder {
|
||||
|
||||
private final SpringApplication application;
|
||||
|
||||
private volatile ConfigurableApplicationContext context;
|
||||
private volatile @Nullable ConfigurableApplicationContext context;
|
||||
|
||||
private SpringApplicationBuilder parent;
|
||||
private @Nullable SpringApplicationBuilder parent;
|
||||
|
||||
private final AtomicBoolean running = new AtomicBoolean();
|
||||
|
||||
@@ -86,7 +89,7 @@ public class SpringApplicationBuilder {
|
||||
|
||||
private final Map<String, Object> defaultProperties = new LinkedHashMap<>();
|
||||
|
||||
private ConfigurableEnvironment environment;
|
||||
private @Nullable ConfigurableEnvironment environment;
|
||||
|
||||
private Set<String> additionalProfiles = new LinkedHashSet<>();
|
||||
|
||||
@@ -98,7 +101,7 @@ public class SpringApplicationBuilder {
|
||||
this(null, sources);
|
||||
}
|
||||
|
||||
public SpringApplicationBuilder(ResourceLoader resourceLoader, Class<?>... sources) {
|
||||
public SpringApplicationBuilder(@Nullable ResourceLoader resourceLoader, Class<?>... sources) {
|
||||
this.application = createSpringApplication(resourceLoader, sources);
|
||||
}
|
||||
|
||||
@@ -111,15 +114,15 @@ public class SpringApplicationBuilder {
|
||||
* @return the {@link SpringApplication} instance
|
||||
* @since 2.6.0
|
||||
*/
|
||||
protected SpringApplication createSpringApplication(ResourceLoader resourceLoader, Class<?>... sources) {
|
||||
protected SpringApplication createSpringApplication(@Nullable ResourceLoader resourceLoader, Class<?>... sources) {
|
||||
return new SpringApplication(resourceLoader, sources);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor for the current application context.
|
||||
* @return the current application context (or null if not yet running)
|
||||
* @return the current application context (or {@code null} if not yet running)
|
||||
*/
|
||||
public ConfigurableApplicationContext context() {
|
||||
public @Nullable ConfigurableApplicationContext context() {
|
||||
return this.context;
|
||||
}
|
||||
|
||||
@@ -140,15 +143,19 @@ public class SpringApplicationBuilder {
|
||||
*/
|
||||
public ConfigurableApplicationContext run(String... args) {
|
||||
if (this.running.get()) {
|
||||
ConfigurableApplicationContext context = this.context;
|
||||
Assert.state(context != null, "No context set");
|
||||
// If already created we just return the existing context
|
||||
return this.context;
|
||||
return context;
|
||||
}
|
||||
configureAsChildIfNecessary(args);
|
||||
if (this.running.compareAndSet(false, true)) {
|
||||
// If not already running copy the sources over and then run.
|
||||
this.context = build().run(args);
|
||||
}
|
||||
return this.context;
|
||||
ConfigurableApplicationContext context = this.context;
|
||||
Assert.state(context != null, "No context set");
|
||||
return context;
|
||||
}
|
||||
|
||||
private void configureAsChildIfNecessary(String... args) {
|
||||
@@ -519,10 +526,10 @@ public class SpringApplicationBuilder {
|
||||
|
||||
/**
|
||||
* Environment for the application context.
|
||||
* @param environment the environment to set.
|
||||
* @param environment the environment to set
|
||||
* @return the current builder
|
||||
*/
|
||||
public SpringApplicationBuilder environment(ConfigurableEnvironment environment) {
|
||||
public SpringApplicationBuilder environment(@Nullable ConfigurableEnvironment environment) {
|
||||
this.application.setEnvironment(environment);
|
||||
this.environment = environment;
|
||||
return this;
|
||||
|
||||
@@ -20,4 +20,7 @@
|
||||
*
|
||||
* @see org.springframework.boot.builder.SpringApplicationBuilder
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.boot.builder;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
+5
-4
@@ -23,6 +23,7 @@ import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor;
|
||||
@@ -165,13 +166,13 @@ public class CloudFoundryVcapEnvironmentPostProcessor implements EnvironmentPost
|
||||
return properties;
|
||||
}
|
||||
|
||||
private void extractPropertiesFromApplication(Properties properties, Map<String, Object> map) {
|
||||
private void extractPropertiesFromApplication(Properties properties, @Nullable Map<String, Object> map) {
|
||||
if (map != null) {
|
||||
flatten(properties, map, "");
|
||||
}
|
||||
}
|
||||
|
||||
private void extractPropertiesFromServices(Properties properties, Map<String, Object> map) {
|
||||
private void extractPropertiesFromServices(Properties properties, @Nullable Map<String, Object> map) {
|
||||
if (map != null) {
|
||||
for (Object services : map.values()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -190,7 +191,7 @@ public class CloudFoundryVcapEnvironmentPostProcessor implements EnvironmentPost
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void flatten(Properties properties, Map<String, Object> input, String path) {
|
||||
private void flatten(Properties properties, Map<String, Object> input, @Nullable String path) {
|
||||
input.forEach((key, value) -> {
|
||||
String name = getPropertyName(path, key);
|
||||
if (value instanceof Map) {
|
||||
@@ -218,7 +219,7 @@ public class CloudFoundryVcapEnvironmentPostProcessor implements EnvironmentPost
|
||||
});
|
||||
}
|
||||
|
||||
private String getPropertyName(String path, String key) {
|
||||
private String getPropertyName(@Nullable String path, String key) {
|
||||
if (!StringUtils.hasText(path)) {
|
||||
return key;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ package org.springframework.boot.cloud;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.EnumerablePropertySource;
|
||||
@@ -198,7 +200,7 @@ public enum CloudPlatform {
|
||||
return isEnforced(binder.bind(PROPERTY_NAME, String.class).orElse(null));
|
||||
}
|
||||
|
||||
private boolean isEnforced(String platform) {
|
||||
private boolean isEnforced(@Nullable String platform) {
|
||||
return name().equalsIgnoreCase(platform);
|
||||
}
|
||||
|
||||
@@ -225,7 +227,7 @@ public enum CloudPlatform {
|
||||
* @param environment the environment
|
||||
* @return the {@link CloudPlatform} or {@code null}
|
||||
*/
|
||||
public static CloudPlatform getActive(Environment environment) {
|
||||
public static @Nullable CloudPlatform getActive(@Nullable Environment environment) {
|
||||
if (environment != null) {
|
||||
for (CloudPlatform cloudPlatform : values()) {
|
||||
if (cloudPlatform.isActive(environment)) {
|
||||
|
||||
@@ -17,4 +17,7 @@
|
||||
/**
|
||||
* Low level support for Cloud deployments.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.boot.cloud;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
+6
-5
@@ -26,6 +26,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
|
||||
import org.springframework.boot.context.event.ApplicationPreparedEvent;
|
||||
@@ -163,7 +164,7 @@ public class ApplicationPidFileWriter implements ApplicationListener<SpringAppli
|
||||
return Boolean.parseBoolean(value);
|
||||
}
|
||||
|
||||
private String getProperty(SpringApplicationEvent event, List<Property> candidates) {
|
||||
private @Nullable String getProperty(SpringApplicationEvent event, List<Property> candidates) {
|
||||
for (Property candidate : candidates) {
|
||||
String value = candidate.getValue(event);
|
||||
if (value != null) {
|
||||
@@ -194,7 +195,7 @@ public class ApplicationPidFileWriter implements ApplicationListener<SpringAppli
|
||||
*/
|
||||
private interface Property {
|
||||
|
||||
String getValue(SpringApplicationEvent event);
|
||||
@Nullable String getValue(SpringApplicationEvent event);
|
||||
|
||||
}
|
||||
|
||||
@@ -213,7 +214,7 @@ public class ApplicationPidFileWriter implements ApplicationListener<SpringAppli
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue(SpringApplicationEvent event) {
|
||||
public @Nullable String getValue(SpringApplicationEvent event) {
|
||||
Environment environment = getEnvironment(event);
|
||||
if (environment == null) {
|
||||
return null;
|
||||
@@ -221,7 +222,7 @@ public class ApplicationPidFileWriter implements ApplicationListener<SpringAppli
|
||||
return environment.getProperty(this.prefix + this.key);
|
||||
}
|
||||
|
||||
private Environment getEnvironment(SpringApplicationEvent event) {
|
||||
private @Nullable Environment getEnvironment(SpringApplicationEvent event) {
|
||||
if (event instanceof ApplicationEnvironmentPreparedEvent environmentPreparedEvent) {
|
||||
return environmentPreparedEvent.getEnvironment();
|
||||
}
|
||||
@@ -248,7 +249,7 @@ public class ApplicationPidFileWriter implements ApplicationListener<SpringAppli
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue(SpringApplicationEvent event) {
|
||||
public @Nullable String getValue(SpringApplicationEvent event) {
|
||||
return SystemProperties.get(this.properties);
|
||||
}
|
||||
|
||||
|
||||
+7
-6
@@ -25,6 +25,7 @@ import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
|
||||
@@ -118,7 +119,7 @@ public class ConfigurationWarningsApplicationContextInitializer
|
||||
* @param registry the {@link BeanDefinitionRegistry}
|
||||
* @return a warning message or {@code null}
|
||||
*/
|
||||
String getWarning(BeanDefinitionRegistry registry);
|
||||
@Nullable String getWarning(BeanDefinitionRegistry registry);
|
||||
|
||||
}
|
||||
|
||||
@@ -137,7 +138,7 @@ public class ConfigurationWarningsApplicationContextInitializer
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWarning(BeanDefinitionRegistry registry) {
|
||||
public @Nullable String getWarning(BeanDefinitionRegistry registry) {
|
||||
Set<String> scannedPackages = getComponentScanningPackages(registry);
|
||||
List<String> problematicPackages = getProblematicPackages(scannedPackages);
|
||||
if (problematicPackages.isEmpty()) {
|
||||
@@ -172,13 +173,13 @@ public class ConfigurationWarningsApplicationContextInitializer
|
||||
}
|
||||
}
|
||||
|
||||
private void addPackages(Set<String> packages, String[] values) {
|
||||
private void addPackages(Set<String> packages, String @Nullable [] values) {
|
||||
if (values != null) {
|
||||
Collections.addAll(packages, values);
|
||||
}
|
||||
}
|
||||
|
||||
private void addClasses(Set<String> packages, String[] values) {
|
||||
private void addClasses(Set<String> packages, String @Nullable [] values) {
|
||||
if (values != null) {
|
||||
for (String value : values) {
|
||||
packages.add(ClassUtils.getPackageName(value));
|
||||
@@ -196,14 +197,14 @@ public class ConfigurationWarningsApplicationContextInitializer
|
||||
return problematicPackages;
|
||||
}
|
||||
|
||||
private boolean isProblematicPackage(String scannedPackage) {
|
||||
private boolean isProblematicPackage(@Nullable String scannedPackage) {
|
||||
if (scannedPackage == null || scannedPackage.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
return PROBLEM_PACKAGES.contains(scannedPackage);
|
||||
}
|
||||
|
||||
private String getDisplayName(String scannedPackage) {
|
||||
private String getDisplayName(@Nullable String scannedPackage) {
|
||||
if (scannedPackage == null || scannedPackage.isEmpty()) {
|
||||
return "the default package";
|
||||
}
|
||||
|
||||
+5
-2
@@ -19,6 +19,8 @@ package org.springframework.boot.context;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
@@ -49,9 +51,10 @@ import org.springframework.core.type.filter.TypeFilter;
|
||||
*/
|
||||
public class TypeExcludeFilter implements TypeFilter, BeanFactoryAware {
|
||||
|
||||
@SuppressWarnings("NullAway.Init")
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private Collection<TypeExcludeFilter> delegates;
|
||||
private @Nullable Collection<TypeExcludeFilter> delegates;
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
@@ -81,7 +84,7 @@ public class TypeExcludeFilter implements TypeFilter, BeanFactoryAware {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
throw new IllegalStateException("TypeExcludeFilter " + getClass() + " has not implemented equals");
|
||||
}
|
||||
|
||||
|
||||
+6
-4
@@ -30,6 +30,8 @@ import java.util.function.UnaryOperator;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportSelector;
|
||||
@@ -61,11 +63,11 @@ public abstract class Configurations {
|
||||
private static final Comparator<Object> COMPARATOR = OrderComparator.INSTANCE
|
||||
.thenComparing((other) -> other.getClass().getName());
|
||||
|
||||
private final UnaryOperator<Collection<Class<?>>> sorter;
|
||||
private final @Nullable UnaryOperator<Collection<Class<?>>> sorter;
|
||||
|
||||
private final Set<Class<?>> classes;
|
||||
|
||||
private final Function<Class<?>, String> beanNameGenerator;
|
||||
private final @Nullable Function<Class<?>, String> beanNameGenerator;
|
||||
|
||||
/**
|
||||
* Create a new {@link Configurations} instance.
|
||||
@@ -85,7 +87,7 @@ public abstract class Configurations {
|
||||
* @param beanNameGenerator an optional function used to generate the bean name
|
||||
* @since 3.4.0
|
||||
*/
|
||||
protected Configurations(UnaryOperator<Collection<Class<?>>> sorter, Collection<Class<?>> classes,
|
||||
protected Configurations(@Nullable UnaryOperator<Collection<Class<?>>> sorter, Collection<Class<?>> classes,
|
||||
Function<Class<?>, String> beanNameGenerator) {
|
||||
Assert.notNull(classes, "'classes' must not be null");
|
||||
this.sorter = (sorter != null) ? sorter : UnaryOperator.identity();
|
||||
@@ -127,7 +129,7 @@ public abstract class Configurations {
|
||||
* @return the bean name
|
||||
* @since 3.4.0
|
||||
*/
|
||||
public String getBeanName(Class<?> beanClass) {
|
||||
public @Nullable String getBeanName(Class<?> beanClass) {
|
||||
return (this.beanNameGenerator != null) ? this.beanNameGenerator.apply(beanClass) : null;
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -27,6 +27,8 @@ import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.io.UrlResource;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -76,7 +78,7 @@ public final class ImportCandidates implements Iterable<String> {
|
||||
* @param classLoader class loader to use for loading
|
||||
* @return list of names of annotated classes
|
||||
*/
|
||||
public static ImportCandidates load(Class<?> annotation, ClassLoader classLoader) {
|
||||
public static ImportCandidates load(Class<?> annotation, @Nullable ClassLoader classLoader) {
|
||||
Assert.notNull(annotation, "'annotation' must not be null");
|
||||
ClassLoader classLoaderToUse = decideClassloader(classLoader);
|
||||
String location = String.format(LOCATION, annotation.getName());
|
||||
@@ -89,7 +91,7 @@ public final class ImportCandidates implements Iterable<String> {
|
||||
return new ImportCandidates(importCandidates);
|
||||
}
|
||||
|
||||
private static ClassLoader decideClassloader(ClassLoader classLoader) {
|
||||
private static ClassLoader decideClassloader(@Nullable ClassLoader classLoader) {
|
||||
if (classLoader == null) {
|
||||
return ImportCandidates.class.getClassLoader();
|
||||
}
|
||||
|
||||
+3
@@ -18,4 +18,7 @@
|
||||
* Classes related to Spring's {@link org.springframework.context.ApplicationContext}
|
||||
* annotations.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.boot.context.annotation;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
+3
-1
@@ -25,6 +25,8 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -120,7 +122,7 @@ public final class ConfigData {
|
||||
* @param propertySource the property source
|
||||
* @return the options to apply
|
||||
*/
|
||||
Options get(PropertySource<?> propertySource);
|
||||
@Nullable Options get(PropertySource<?> propertySource);
|
||||
|
||||
/**
|
||||
* Create a new {@link PropertySourceOptions} instance that always returns the
|
||||
|
||||
+8
-6
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.boot.context.config;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.cloud.CloudPlatform;
|
||||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
import org.springframework.core.env.Environment;
|
||||
@@ -29,9 +31,9 @@ import org.springframework.core.style.ToStringCreator;
|
||||
*/
|
||||
class ConfigDataActivationContext {
|
||||
|
||||
private final CloudPlatform cloudPlatform;
|
||||
private final @Nullable CloudPlatform cloudPlatform;
|
||||
|
||||
private final Profiles profiles;
|
||||
private final @Nullable Profiles profiles;
|
||||
|
||||
/**
|
||||
* Create a new {@link ConfigDataActivationContext} instance before any profiles have
|
||||
@@ -50,12 +52,12 @@ class ConfigDataActivationContext {
|
||||
* @param cloudPlatform the cloud platform
|
||||
* @param profiles the profiles
|
||||
*/
|
||||
ConfigDataActivationContext(CloudPlatform cloudPlatform, Profiles profiles) {
|
||||
ConfigDataActivationContext(@Nullable CloudPlatform cloudPlatform, Profiles profiles) {
|
||||
this.cloudPlatform = cloudPlatform;
|
||||
this.profiles = profiles;
|
||||
}
|
||||
|
||||
private CloudPlatform deduceCloudPlatform(Environment environment, Binder binder) {
|
||||
private @Nullable CloudPlatform deduceCloudPlatform(Environment environment, Binder binder) {
|
||||
for (CloudPlatform candidate : CloudPlatform.values()) {
|
||||
if (candidate.isEnforced(binder)) {
|
||||
return candidate;
|
||||
@@ -77,7 +79,7 @@ class ConfigDataActivationContext {
|
||||
* Return the active {@link CloudPlatform} or {@code null}.
|
||||
* @return the active cloud platform
|
||||
*/
|
||||
CloudPlatform getCloudPlatform() {
|
||||
@Nullable CloudPlatform getCloudPlatform() {
|
||||
return this.cloudPlatform;
|
||||
}
|
||||
|
||||
@@ -85,7 +87,7 @@ class ConfigDataActivationContext {
|
||||
* Return profile information if it is available.
|
||||
* @return profile information or {@code null}
|
||||
*/
|
||||
Profiles getProfiles() {
|
||||
@Nullable Profiles getProfiles() {
|
||||
return this.profiles;
|
||||
}
|
||||
|
||||
|
||||
+5
-2
@@ -24,6 +24,7 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.BootstrapRegistry.InstanceSupplier;
|
||||
import org.springframework.boot.BootstrapRegistry.Scope;
|
||||
@@ -43,6 +44,7 @@ import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
import org.springframework.core.log.LogMessage;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -137,7 +139,7 @@ class ConfigDataEnvironment {
|
||||
*/
|
||||
ConfigDataEnvironment(DeferredLogFactory logFactory, ConfigurableBootstrapContext bootstrapContext,
|
||||
ConfigurableEnvironment environment, ResourceLoader resourceLoader, Collection<String> additionalProfiles,
|
||||
ConfigDataEnvironmentUpdateListener environmentUpdateListener) {
|
||||
@Nullable ConfigDataEnvironmentUpdateListener environmentUpdateListener) {
|
||||
Binder binder = Binder.get(environment);
|
||||
this.logFactory = logFactory;
|
||||
this.logger = logFactory.getLog(getClass());
|
||||
@@ -321,7 +323,7 @@ class ConfigDataEnvironment {
|
||||
}
|
||||
|
||||
private void registerBootstrapBinder(ConfigDataEnvironmentContributors contributors,
|
||||
ConfigDataActivationContext activationContext, BinderOption... binderOptions) {
|
||||
@Nullable ConfigDataActivationContext activationContext, BinderOption... binderOptions) {
|
||||
this.bootstrapContext.register(Binder.class,
|
||||
InstanceSupplier.from(() -> contributors.getBinder(activationContext, binderOptions))
|
||||
.withScope(Scope.PROTOTYPE));
|
||||
@@ -336,6 +338,7 @@ class ConfigDataEnvironment {
|
||||
applyContributor(contributors, activationContext, propertySources);
|
||||
DefaultPropertiesPropertySource.moveToEnd(propertySources);
|
||||
Profiles profiles = activationContext.getProfiles();
|
||||
Assert.state(profiles != null, "'profiles' must not be null");
|
||||
this.logger.trace(LogMessage.format("Setting default profiles: %s", profiles.getDefault()));
|
||||
this.environment.setDefaultProfiles(StringUtils.toStringArray(profiles.getDefault()));
|
||||
this.logger.trace(LogMessage.format("Setting active profiles: %s", profiles.getActive()));
|
||||
|
||||
+28
-21
@@ -26,6 +26,8 @@ import java.util.NoSuchElementException;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
import org.springframework.boot.context.properties.bind.PlaceholdersResolver;
|
||||
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
|
||||
@@ -33,6 +35,7 @@ import org.springframework.boot.origin.OriginLookup;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.lang.Contract;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
@@ -58,17 +61,17 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
|
||||
private static final ConfigData.Options EMPTY_LOCATION_OPTIONS = ConfigData.Options
|
||||
.of(ConfigData.Option.IGNORE_IMPORTS);
|
||||
|
||||
private final ConfigDataLocation location;
|
||||
private final @Nullable ConfigDataLocation location;
|
||||
|
||||
private final ConfigDataResource resource;
|
||||
private final @Nullable ConfigDataResource resource;
|
||||
|
||||
private final boolean fromProfileSpecificImport;
|
||||
|
||||
private final PropertySource<?> propertySource;
|
||||
private final @Nullable PropertySource<?> propertySource;
|
||||
|
||||
private final ConfigurationPropertySource configurationPropertySource;
|
||||
private final @Nullable ConfigurationPropertySource configurationPropertySource;
|
||||
|
||||
private final ConfigDataProperties properties;
|
||||
private final @Nullable ConfigDataProperties properties;
|
||||
|
||||
private final ConfigData.Options configDataOptions;
|
||||
|
||||
@@ -93,10 +96,12 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
|
||||
* @param children the children of this contributor at each {@link ImportPhase}
|
||||
* @param conversionService the conversion service to use
|
||||
*/
|
||||
ConfigDataEnvironmentContributor(Kind kind, ConfigDataLocation location, ConfigDataResource resource,
|
||||
boolean fromProfileSpecificImport, PropertySource<?> propertySource,
|
||||
ConfigurationPropertySource configurationPropertySource, ConfigDataProperties properties,
|
||||
ConfigData.Options configDataOptions, Map<ImportPhase, List<ConfigDataEnvironmentContributor>> children,
|
||||
ConfigDataEnvironmentContributor(Kind kind, @Nullable ConfigDataLocation location,
|
||||
@Nullable ConfigDataResource resource, boolean fromProfileSpecificImport,
|
||||
@Nullable PropertySource<?> propertySource,
|
||||
@Nullable ConfigurationPropertySource configurationPropertySource,
|
||||
@Nullable ConfigDataProperties properties, ConfigData.@Nullable Options configDataOptions,
|
||||
@Nullable Map<ImportPhase, List<ConfigDataEnvironmentContributor>> children,
|
||||
ConversionService conversionService) {
|
||||
this.kind = kind;
|
||||
this.location = location;
|
||||
@@ -118,7 +123,7 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
|
||||
return this.kind;
|
||||
}
|
||||
|
||||
ConfigDataLocation getLocation() {
|
||||
@Nullable ConfigDataLocation getLocation() {
|
||||
return this.location;
|
||||
}
|
||||
|
||||
@@ -127,7 +132,7 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
|
||||
* @param activationContext the activation context
|
||||
* @return if the contributor is active
|
||||
*/
|
||||
boolean isActive(ConfigDataActivationContext activationContext) {
|
||||
boolean isActive(@Nullable ConfigDataActivationContext activationContext) {
|
||||
if (this.kind == Kind.UNBOUND_IMPORT) {
|
||||
return false;
|
||||
}
|
||||
@@ -138,7 +143,7 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
|
||||
* Return the resource that contributed this instance.
|
||||
* @return the resource or {@code null}
|
||||
*/
|
||||
ConfigDataResource getResource() {
|
||||
@Nullable ConfigDataResource getResource() {
|
||||
return this.resource;
|
||||
}
|
||||
|
||||
@@ -154,7 +159,7 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
|
||||
* Return the property source for this contributor.
|
||||
* @return the property source or {@code null}
|
||||
*/
|
||||
PropertySource<?> getPropertySource() {
|
||||
@Nullable PropertySource<?> getPropertySource() {
|
||||
return this.propertySource;
|
||||
}
|
||||
|
||||
@@ -162,7 +167,7 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
|
||||
* Return the configuration property source for this contributor.
|
||||
* @return the configuration property source or {@code null}
|
||||
*/
|
||||
ConfigurationPropertySource getConfigurationPropertySource() {
|
||||
@Nullable ConfigurationPropertySource getConfigurationPropertySource() {
|
||||
return this.configurationPropertySource;
|
||||
}
|
||||
|
||||
@@ -239,7 +244,7 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
|
||||
* @return a new contributor instance
|
||||
*/
|
||||
ConfigDataEnvironmentContributor withBoundProperties(Iterable<ConfigDataEnvironmentContributor> contributors,
|
||||
ConfigDataActivationContext activationContext) {
|
||||
@Nullable ConfigDataActivationContext activationContext) {
|
||||
Iterable<ConfigurationPropertySource> sources = Collections.singleton(getConfigurationPropertySource());
|
||||
PlaceholdersResolver placeholdersResolver = new ConfigDataEnvironmentContributorPlaceholdersResolver(
|
||||
contributors, activationContext, this, true, this.conversionService);
|
||||
@@ -305,7 +310,8 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
|
||||
return contributor;
|
||||
}
|
||||
|
||||
private boolean hasAnyProfileSpecificChildren(List<ConfigDataEnvironmentContributor> contributors) {
|
||||
@Contract("null -> false")
|
||||
private boolean hasAnyProfileSpecificChildren(@Nullable List<ConfigDataEnvironmentContributor> contributors) {
|
||||
if (CollectionUtils.isEmpty(contributors)) {
|
||||
return false;
|
||||
}
|
||||
@@ -441,7 +447,8 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
|
||||
propertySource, asConfigurationPropertySource(propertySource), null, options, null, conversionService);
|
||||
}
|
||||
|
||||
private static ConfigurationPropertySource asConfigurationPropertySource(PropertySource<?> propertySource) {
|
||||
private static @Nullable ConfigurationPropertySource asConfigurationPropertySource(
|
||||
PropertySource<?> propertySource) {
|
||||
ConfigurationPropertySource configurationPropertySource = ConfigurationPropertySource.from(propertySource);
|
||||
if (configurationPropertySource != null && propertySource instanceof OriginLookup<?> originLookup) {
|
||||
configurationPropertySource = configurationPropertySource.withPrefix(originLookup.getPrefix());
|
||||
@@ -521,7 +528,7 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
|
||||
* @param activationContext the activation context
|
||||
* @return the import phase
|
||||
*/
|
||||
static ImportPhase get(ConfigDataActivationContext activationContext) {
|
||||
static ImportPhase get(@Nullable ConfigDataActivationContext activationContext) {
|
||||
if (activationContext != null && activationContext.getProfiles() != null) {
|
||||
return AFTER_PROFILE_ACTIVATION;
|
||||
}
|
||||
@@ -535,13 +542,13 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
|
||||
*/
|
||||
private final class ContributorIterator implements Iterator<ConfigDataEnvironmentContributor> {
|
||||
|
||||
private ImportPhase phase;
|
||||
private @Nullable ImportPhase phase;
|
||||
|
||||
private Iterator<ConfigDataEnvironmentContributor> children;
|
||||
|
||||
private Iterator<ConfigDataEnvironmentContributor> current;
|
||||
|
||||
private ConfigDataEnvironmentContributor next;
|
||||
private @Nullable ConfigDataEnvironmentContributor next;
|
||||
|
||||
private ContributorIterator() {
|
||||
this.phase = ImportPhase.AFTER_PROFILE_ACTIVATION;
|
||||
@@ -564,7 +571,7 @@ class ConfigDataEnvironmentContributor implements Iterable<ConfigDataEnvironment
|
||||
return next;
|
||||
}
|
||||
|
||||
private ConfigDataEnvironmentContributor fetchIfNecessary() {
|
||||
private @Nullable ConfigDataEnvironmentContributor fetchIfNecessary() {
|
||||
if (this.next != null) {
|
||||
return this.next;
|
||||
}
|
||||
|
||||
+12
-7
@@ -16,12 +16,15 @@
|
||||
|
||||
package org.springframework.boot.context.config;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.context.config.ConfigDataEnvironmentContributor.Kind;
|
||||
import org.springframework.boot.context.properties.bind.PlaceholdersResolver;
|
||||
import org.springframework.boot.origin.Origin;
|
||||
import org.springframework.boot.origin.OriginLookup;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.PropertyPlaceholderHelper;
|
||||
import org.springframework.util.SystemPropertyUtils;
|
||||
|
||||
@@ -37,19 +40,20 @@ class ConfigDataEnvironmentContributorPlaceholdersResolver implements Placeholde
|
||||
|
||||
private final Iterable<ConfigDataEnvironmentContributor> contributors;
|
||||
|
||||
private final ConfigDataActivationContext activationContext;
|
||||
private final @Nullable ConfigDataActivationContext activationContext;
|
||||
|
||||
private final boolean failOnResolveFromInactiveContributor;
|
||||
|
||||
private final PropertyPlaceholderHelper helper;
|
||||
|
||||
private final ConfigDataEnvironmentContributor activeContributor;
|
||||
private final @Nullable ConfigDataEnvironmentContributor activeContributor;
|
||||
|
||||
private final ConversionService conversionService;
|
||||
|
||||
ConfigDataEnvironmentContributorPlaceholdersResolver(Iterable<ConfigDataEnvironmentContributor> contributors,
|
||||
ConfigDataActivationContext activationContext, ConfigDataEnvironmentContributor activeContributor,
|
||||
boolean failOnResolveFromInactiveContributor, ConversionService conversionService) {
|
||||
@Nullable ConfigDataActivationContext activationContext,
|
||||
@Nullable ConfigDataEnvironmentContributor activeContributor, boolean failOnResolveFromInactiveContributor,
|
||||
ConversionService conversionService) {
|
||||
this.contributors = contributors;
|
||||
this.activationContext = activationContext;
|
||||
this.activeContributor = activeContributor;
|
||||
@@ -61,14 +65,14 @@ class ConfigDataEnvironmentContributorPlaceholdersResolver implements Placeholde
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolvePlaceholders(Object value) {
|
||||
public @Nullable Object resolvePlaceholders(@Nullable Object value) {
|
||||
if (value instanceof String string) {
|
||||
return this.helper.replacePlaceholders(string, this::resolvePlaceholder);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private String resolvePlaceholder(String placeholder) {
|
||||
private @Nullable String resolvePlaceholder(String placeholder) {
|
||||
Object result = null;
|
||||
for (ConfigDataEnvironmentContributor contributor : this.contributors) {
|
||||
PropertySource<?> propertySource = contributor.getPropertySource();
|
||||
@@ -76,6 +80,7 @@ class ConfigDataEnvironmentContributorPlaceholdersResolver implements Placeholde
|
||||
if (value != null && !isActive(contributor)) {
|
||||
if (this.failOnResolveFromInactiveContributor) {
|
||||
ConfigDataResource resource = contributor.getResource();
|
||||
Assert.state(propertySource != null, "'propertySource' can't be null here");
|
||||
Origin origin = OriginLookup.getOrigin(propertySource, placeholder);
|
||||
throw new InactiveConfigDataAccessException(propertySource, resource, placeholder, origin);
|
||||
}
|
||||
@@ -97,7 +102,7 @@ class ConfigDataEnvironmentContributorPlaceholdersResolver implements Placeholde
|
||||
.isActive(this.activationContext);
|
||||
}
|
||||
|
||||
private String convertValueIfNecessary(Object value) {
|
||||
private @Nullable String convertValueIfNecessary(Object value) {
|
||||
return (value instanceof String string) ? string : this.conversionService.convert(value, String.class);
|
||||
}
|
||||
|
||||
|
||||
+15
-14
@@ -27,6 +27,7 @@ import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.ConfigurableBootstrapContext;
|
||||
import org.springframework.boot.context.config.ConfigDataEnvironmentContributor.ImportPhase;
|
||||
@@ -102,7 +103,7 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen
|
||||
* imports have been processed
|
||||
*/
|
||||
ConfigDataEnvironmentContributors withProcessedImports(ConfigDataImporter importer,
|
||||
ConfigDataActivationContext activationContext) {
|
||||
@Nullable ConfigDataActivationContext activationContext) {
|
||||
ImportPhase importPhase = ImportPhase.get(activationContext);
|
||||
this.logger.trace(LogMessage.format("Processing imports for phase %s. %s", importPhase,
|
||||
(activationContext != null) ? activationContext : "no activation context"));
|
||||
@@ -152,8 +153,8 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen
|
||||
return this.bootstrapContext;
|
||||
}
|
||||
|
||||
private ConfigDataEnvironmentContributor getNextToProcess(ConfigDataEnvironmentContributors contributors,
|
||||
ConfigDataActivationContext activationContext, ImportPhase importPhase) {
|
||||
private @Nullable ConfigDataEnvironmentContributor getNextToProcess(ConfigDataEnvironmentContributors contributors,
|
||||
@Nullable ConfigDataActivationContext activationContext, ImportPhase importPhase) {
|
||||
for (ConfigDataEnvironmentContributor contributor : contributors.getRoot()) {
|
||||
if (contributor.getKind() == Kind.UNBOUND_IMPORT
|
||||
|| isActiveWithUnprocessedImports(activationContext, importPhase, contributor)) {
|
||||
@@ -163,7 +164,7 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isActiveWithUnprocessedImports(ConfigDataActivationContext activationContext,
|
||||
private boolean isActiveWithUnprocessedImports(@Nullable ConfigDataActivationContext activationContext,
|
||||
ImportPhase importPhase, ConfigDataEnvironmentContributor contributor) {
|
||||
return contributor.isActive(activationContext) && contributor.hasUnprocessedImports(importPhase);
|
||||
}
|
||||
@@ -203,7 +204,7 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen
|
||||
* @param options binder options to apply
|
||||
* @return a binder instance
|
||||
*/
|
||||
Binder getBinder(ConfigDataActivationContext activationContext, BinderOption... options) {
|
||||
Binder getBinder(@Nullable ConfigDataActivationContext activationContext, BinderOption... options) {
|
||||
return getBinder(activationContext, NO_CONTRIBUTOR_FILTER, options);
|
||||
}
|
||||
|
||||
@@ -214,8 +215,8 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen
|
||||
* @param options binder options to apply
|
||||
* @return a binder instance
|
||||
*/
|
||||
Binder getBinder(ConfigDataActivationContext activationContext, Predicate<ConfigDataEnvironmentContributor> filter,
|
||||
BinderOption... options) {
|
||||
Binder getBinder(@Nullable ConfigDataActivationContext activationContext,
|
||||
Predicate<ConfigDataEnvironmentContributor> filter, BinderOption... options) {
|
||||
return getBinder(activationContext, filter, asBinderOptionsSet(options));
|
||||
}
|
||||
|
||||
@@ -224,7 +225,7 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen
|
||||
: EnumSet.copyOf(Arrays.asList(options));
|
||||
}
|
||||
|
||||
private Binder getBinder(ConfigDataActivationContext activationContext,
|
||||
private Binder getBinder(@Nullable ConfigDataActivationContext activationContext,
|
||||
Predicate<ConfigDataEnvironmentContributor> filter, Set<BinderOption> options) {
|
||||
boolean failOnInactiveSource = options.contains(BinderOption.FAIL_ON_BIND_TO_INACTIVE_SOURCE);
|
||||
Iterable<ConfigurationPropertySource> sources = () -> getBinderSources(
|
||||
@@ -279,12 +280,12 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen
|
||||
|
||||
private final ConfigDataEnvironmentContributor contributor;
|
||||
|
||||
private final ConfigDataActivationContext activationContext;
|
||||
private final @Nullable ConfigDataActivationContext activationContext;
|
||||
|
||||
private volatile Binder binder;
|
||||
private volatile @Nullable Binder binder;
|
||||
|
||||
ContributorConfigDataLocationResolverContext(ConfigDataEnvironmentContributors contributors,
|
||||
ConfigDataEnvironmentContributor contributor, ConfigDataActivationContext activationContext) {
|
||||
ConfigDataEnvironmentContributor contributor, @Nullable ConfigDataActivationContext activationContext) {
|
||||
this.contributors = contributors;
|
||||
this.contributor = contributor;
|
||||
this.activationContext = activationContext;
|
||||
@@ -301,7 +302,7 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigDataResource getParent() {
|
||||
public @Nullable ConfigDataResource getParent() {
|
||||
return this.contributor.getResource();
|
||||
}
|
||||
|
||||
@@ -314,9 +315,9 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen
|
||||
|
||||
private class InactiveSourceChecker implements BindHandler {
|
||||
|
||||
private final ConfigDataActivationContext activationContext;
|
||||
private final @Nullable ConfigDataActivationContext activationContext;
|
||||
|
||||
InactiveSourceChecker(ConfigDataActivationContext activationContext) {
|
||||
InactiveSourceChecker(@Nullable ConfigDataActivationContext activationContext) {
|
||||
this.activationContext = activationContext;
|
||||
}
|
||||
|
||||
|
||||
+8
-7
@@ -22,6 +22,7 @@ import java.util.Collections;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.ConfigurableBootstrapContext;
|
||||
import org.springframework.boot.DefaultBootstrapContext;
|
||||
@@ -63,7 +64,7 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces
|
||||
|
||||
private final ConfigurableBootstrapContext bootstrapContext;
|
||||
|
||||
private final ConfigDataEnvironmentUpdateListener environmentUpdateListener;
|
||||
private final @Nullable ConfigDataEnvironmentUpdateListener environmentUpdateListener;
|
||||
|
||||
public ConfigDataEnvironmentPostProcessor(DeferredLogFactory logFactory,
|
||||
ConfigurableBootstrapContext bootstrapContext) {
|
||||
@@ -72,7 +73,7 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces
|
||||
|
||||
private ConfigDataEnvironmentPostProcessor(DeferredLogFactory logFactory,
|
||||
ConfigurableBootstrapContext bootstrapContext,
|
||||
ConfigDataEnvironmentUpdateListener environmentUpdateListener) {
|
||||
@Nullable ConfigDataEnvironmentUpdateListener environmentUpdateListener) {
|
||||
this.logFactory = logFactory;
|
||||
this.logger = logFactory.getLog(getClass());
|
||||
this.bootstrapContext = bootstrapContext;
|
||||
@@ -89,7 +90,7 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces
|
||||
postProcessEnvironment(environment, application.getResourceLoader(), application.getAdditionalProfiles());
|
||||
}
|
||||
|
||||
void postProcessEnvironment(ConfigurableEnvironment environment, ResourceLoader resourceLoader,
|
||||
void postProcessEnvironment(ConfigurableEnvironment environment, @Nullable ResourceLoader resourceLoader,
|
||||
Collection<String> additionalProfiles) {
|
||||
this.logger.trace("Post-processing environment to add config data");
|
||||
resourceLoader = (resourceLoader != null) ? resourceLoader : new DefaultResourceLoader();
|
||||
@@ -123,7 +124,7 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces
|
||||
* @param additionalProfiles any additional profiles that should be applied
|
||||
*/
|
||||
public static void applyTo(ConfigurableEnvironment environment, ResourceLoader resourceLoader,
|
||||
ConfigurableBootstrapContext bootstrapContext, String... additionalProfiles) {
|
||||
@Nullable ConfigurableBootstrapContext bootstrapContext, String... additionalProfiles) {
|
||||
applyTo(environment, resourceLoader, bootstrapContext, Arrays.asList(additionalProfiles));
|
||||
}
|
||||
|
||||
@@ -137,8 +138,8 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces
|
||||
* throw-away context
|
||||
* @param additionalProfiles any additional profiles that should be applied
|
||||
*/
|
||||
public static void applyTo(ConfigurableEnvironment environment, ResourceLoader resourceLoader,
|
||||
ConfigurableBootstrapContext bootstrapContext, Collection<String> additionalProfiles) {
|
||||
public static void applyTo(ConfigurableEnvironment environment, @Nullable ResourceLoader resourceLoader,
|
||||
@Nullable ConfigurableBootstrapContext bootstrapContext, Collection<String> additionalProfiles) {
|
||||
DeferredLogFactory logFactory = Supplier::get;
|
||||
bootstrapContext = (bootstrapContext != null) ? bootstrapContext : new DefaultBootstrapContext();
|
||||
ConfigDataEnvironmentPostProcessor postProcessor = new ConfigDataEnvironmentPostProcessor(logFactory,
|
||||
@@ -160,7 +161,7 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces
|
||||
* {@link Environment} updates.
|
||||
*/
|
||||
public static void applyTo(ConfigurableEnvironment environment, ResourceLoader resourceLoader,
|
||||
ConfigurableBootstrapContext bootstrapContext, Collection<String> additionalProfiles,
|
||||
@Nullable ConfigurableBootstrapContext bootstrapContext, Collection<String> additionalProfiles,
|
||||
ConfigDataEnvironmentUpdateListener environmentUpdateListener) {
|
||||
DeferredLogFactory logFactory = Supplier::get;
|
||||
bootstrapContext = (bootstrapContext != null) ? bootstrapContext : new DefaultBootstrapContext();
|
||||
|
||||
+4
-2
@@ -18,6 +18,8 @@ package org.springframework.boot.context.config;
|
||||
|
||||
import java.util.EventListener;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.context.config.ConfigData.Options;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
@@ -43,8 +45,8 @@ public interface ConfigDataEnvironmentUpdateListener extends EventListener {
|
||||
* @param location the original {@link ConfigDataLocation} of the source.
|
||||
* @param resource the {@link ConfigDataResource} of the source.
|
||||
*/
|
||||
default void onPropertySourceAdded(PropertySource<?> propertySource, ConfigDataLocation location,
|
||||
ConfigDataResource resource) {
|
||||
default void onPropertySourceAdded(PropertySource<?> propertySource, @Nullable ConfigDataLocation location,
|
||||
@Nullable ConfigDataResource resource) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3
-1
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.boot.context.config;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Abstract base class for configuration data exceptions.
|
||||
*
|
||||
@@ -30,7 +32,7 @@ public abstract class ConfigDataException extends RuntimeException {
|
||||
* @param message the exception message
|
||||
* @param cause the exception cause
|
||||
*/
|
||||
protected ConfigDataException(String message, Throwable cause) {
|
||||
protected ConfigDataException(String message, @Nullable Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
|
||||
+8
-5
@@ -26,6 +26,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.logging.DeferredLogFactory;
|
||||
import org.springframework.core.log.LogMessage;
|
||||
@@ -78,7 +79,7 @@ class ConfigDataImporter {
|
||||
* @param locations the locations to resolve
|
||||
* @return a map of the loaded locations and data
|
||||
*/
|
||||
Map<ConfigDataResolutionResult, ConfigData> resolveAndLoad(ConfigDataActivationContext activationContext,
|
||||
Map<ConfigDataResolutionResult, ConfigData> resolveAndLoad(@Nullable ConfigDataActivationContext activationContext,
|
||||
ConfigDataLocationResolverContext locationResolverContext, ConfigDataLoaderContext loaderContext,
|
||||
List<ConfigDataLocation> locations) {
|
||||
try {
|
||||
@@ -92,7 +93,7 @@ class ConfigDataImporter {
|
||||
}
|
||||
|
||||
private List<ConfigDataResolutionResult> resolve(ConfigDataLocationResolverContext locationResolverContext,
|
||||
Profiles profiles, List<ConfigDataLocation> locations) {
|
||||
@Nullable Profiles profiles, List<ConfigDataLocation> locations) {
|
||||
List<ConfigDataResolutionResult> resolved = new ArrayList<>(locations.size());
|
||||
for (ConfigDataLocation location : locations) {
|
||||
resolved.addAll(resolve(locationResolverContext, profiles, location));
|
||||
@@ -101,7 +102,7 @@ class ConfigDataImporter {
|
||||
}
|
||||
|
||||
private List<ConfigDataResolutionResult> resolve(ConfigDataLocationResolverContext locationResolverContext,
|
||||
Profiles profiles, ConfigDataLocation location) {
|
||||
@Nullable Profiles profiles, ConfigDataLocation location) {
|
||||
try {
|
||||
return this.resolvers.resolve(locationResolverContext, location, profiles);
|
||||
}
|
||||
@@ -145,14 +146,16 @@ class ConfigDataImporter {
|
||||
return Collections.unmodifiableMap(result);
|
||||
}
|
||||
|
||||
private void handle(ConfigDataNotFoundException ex, ConfigDataLocation location, ConfigDataResource resource) {
|
||||
private void handle(ConfigDataNotFoundException ex, ConfigDataLocation location,
|
||||
@Nullable ConfigDataResource resource) {
|
||||
if (ex instanceof ConfigDataResourceNotFoundException notFoundException) {
|
||||
ex = notFoundException.withLocation(location);
|
||||
}
|
||||
getNotFoundAction(location, resource).handle(this.logger, ex);
|
||||
}
|
||||
|
||||
private ConfigDataNotFoundAction getNotFoundAction(ConfigDataLocation location, ConfigDataResource resource) {
|
||||
private ConfigDataNotFoundAction getNotFoundAction(ConfigDataLocation location,
|
||||
@Nullable ConfigDataResource resource) {
|
||||
if (location.isOptional() || (resource != null && resource.isOptional())) {
|
||||
return ConfigDataNotFoundAction.IGNORE;
|
||||
}
|
||||
|
||||
+3
-1
@@ -18,6 +18,8 @@ package org.springframework.boot.context.config;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.BootstrapContext;
|
||||
import org.springframework.boot.BootstrapRegistry;
|
||||
import org.springframework.boot.ConfigurableBootstrapContext;
|
||||
@@ -61,7 +63,7 @@ public interface ConfigDataLoader<R extends ConfigDataResource> {
|
||||
* @throws IOException on IO error
|
||||
* @throws ConfigDataResourceNotFoundException if the resource cannot be found
|
||||
*/
|
||||
ConfigData load(ConfigDataLoaderContext context, R resource)
|
||||
@Nullable ConfigData load(ConfigDataLoaderContext context, R resource)
|
||||
throws IOException, ConfigDataResourceNotFoundException;
|
||||
|
||||
}
|
||||
|
||||
+4
-2
@@ -22,6 +22,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.BootstrapContext;
|
||||
import org.springframework.boot.BootstrapRegistry;
|
||||
@@ -78,7 +79,7 @@ class ConfigDataLoaders {
|
||||
return Collections.unmodifiableList(resourceTypes);
|
||||
}
|
||||
|
||||
private Class<?> getResourceType(ConfigDataLoader<?> loader) {
|
||||
private @Nullable Class<?> getResourceType(ConfigDataLoader<?> loader) {
|
||||
return ResolvableType.forClass(loader.getClass()).as(ConfigDataLoader.class).resolveGeneric();
|
||||
}
|
||||
|
||||
@@ -90,7 +91,8 @@ class ConfigDataLoaders {
|
||||
* @return the loaded {@link ConfigData}
|
||||
* @throws IOException on IO error
|
||||
*/
|
||||
<R extends ConfigDataResource> ConfigData load(ConfigDataLoaderContext context, R resource) throws IOException {
|
||||
<R extends ConfigDataResource> @Nullable ConfigData load(ConfigDataLoaderContext context, R resource)
|
||||
throws IOException {
|
||||
ConfigDataLoader<R> loader = getLoader(context, resource);
|
||||
this.logger.trace(LogMessage.of(() -> "Loading " + resource + " using loader " + loader.getClass().getName()));
|
||||
return loader.load(context, resource);
|
||||
|
||||
+20
-7
@@ -16,8 +16,11 @@
|
||||
|
||||
package org.springframework.boot.context.config;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.origin.Origin;
|
||||
import org.springframework.boot.origin.OriginProvider;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@@ -44,9 +47,9 @@ public final class ConfigDataLocation implements OriginProvider {
|
||||
|
||||
private final String value;
|
||||
|
||||
private final Origin origin;
|
||||
private final @Nullable Origin origin;
|
||||
|
||||
private ConfigDataLocation(boolean optional, String value, Origin origin) {
|
||||
private ConfigDataLocation(boolean optional, String value, @Nullable Origin origin) {
|
||||
this.value = value;
|
||||
this.optional = optional;
|
||||
this.origin = origin;
|
||||
@@ -93,7 +96,7 @@ public final class ConfigDataLocation implements OriginProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Origin getOrigin() {
|
||||
public @Nullable Origin getOrigin() {
|
||||
return this.origin;
|
||||
}
|
||||
|
||||
@@ -118,7 +121,10 @@ public final class ConfigDataLocation implements OriginProvider {
|
||||
String[] values = StringUtils.delimitedListToStringArray(toString(), delimiter);
|
||||
ConfigDataLocation[] result = new ConfigDataLocation[values.length];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
result[i] = of(values[i]).withOrigin(getOrigin());
|
||||
int index = i;
|
||||
ConfigDataLocation configDataLocation = of(values[index]);
|
||||
Assert.state(configDataLocation != null, () -> "Unable to parse '%s'".formatted(values[index]));
|
||||
result[i] = configDataLocation.withOrigin(getOrigin());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -150,7 +156,7 @@ public final class ConfigDataLocation implements OriginProvider {
|
||||
* @param origin the origin to set
|
||||
* @return a new {@link ConfigDataLocation} instance.
|
||||
*/
|
||||
ConfigDataLocation withOrigin(Origin origin) {
|
||||
ConfigDataLocation withOrigin(@Nullable Origin origin) {
|
||||
return new ConfigDataLocation(this.optional, this.value, origin);
|
||||
}
|
||||
|
||||
@@ -160,9 +166,16 @@ public final class ConfigDataLocation implements OriginProvider {
|
||||
* @return a {@link ConfigDataLocation} instance or {@code null} if no location was
|
||||
* provided
|
||||
*/
|
||||
public static ConfigDataLocation of(String location) {
|
||||
public static @Nullable ConfigDataLocation of(@Nullable String location) {
|
||||
boolean optional = location != null && location.startsWith(OPTIONAL_PREFIX);
|
||||
String value = (!optional) ? location : location.substring(OPTIONAL_PREFIX.length());
|
||||
String value;
|
||||
if (optional) {
|
||||
Assert.state(location != null, "'location' can't be null here");
|
||||
value = location.substring(OPTIONAL_PREFIX.length());
|
||||
}
|
||||
else {
|
||||
value = location;
|
||||
}
|
||||
if (!StringUtils.hasText(value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
+5
-3
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.boot.context.config;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.origin.Origin;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -43,7 +45,7 @@ public class ConfigDataLocationNotFoundException extends ConfigDataNotFoundExcep
|
||||
* @param location the location that could not be found
|
||||
* @param cause the exception cause
|
||||
*/
|
||||
public ConfigDataLocationNotFoundException(ConfigDataLocation location, Throwable cause) {
|
||||
public ConfigDataLocationNotFoundException(ConfigDataLocation location, @Nullable Throwable cause) {
|
||||
this(location, getMessage(location), cause);
|
||||
}
|
||||
|
||||
@@ -54,7 +56,7 @@ public class ConfigDataLocationNotFoundException extends ConfigDataNotFoundExcep
|
||||
* @param cause the exception cause
|
||||
* @since 2.4.7
|
||||
*/
|
||||
public ConfigDataLocationNotFoundException(ConfigDataLocation location, String message, Throwable cause) {
|
||||
public ConfigDataLocationNotFoundException(ConfigDataLocation location, String message, @Nullable Throwable cause) {
|
||||
super(message, cause);
|
||||
Assert.notNull(location, "'location' must not be null");
|
||||
this.location = location;
|
||||
@@ -69,7 +71,7 @@ public class ConfigDataLocationNotFoundException extends ConfigDataNotFoundExcep
|
||||
}
|
||||
|
||||
@Override
|
||||
public Origin getOrigin() {
|
||||
public @Nullable Origin getOrigin() {
|
||||
return Origin.from(this.location);
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.boot.context.config;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.ConfigurableBootstrapContext;
|
||||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
import org.springframework.boot.env.EnvironmentPostProcessor;
|
||||
@@ -41,7 +43,7 @@ public interface ConfigDataLocationResolverContext {
|
||||
* or {@code null} if there is no available parent.
|
||||
* @return the parent location
|
||||
*/
|
||||
ConfigDataResource getParent();
|
||||
@Nullable ConfigDataResource getParent();
|
||||
|
||||
/**
|
||||
* Provides access to the {@link ConfigurableBootstrapContext} shared across all
|
||||
|
||||
+5
-4
@@ -22,6 +22,7 @@ import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.BootstrapContext;
|
||||
import org.springframework.boot.BootstrapRegistry;
|
||||
@@ -84,8 +85,8 @@ class ConfigDataLocationResolvers {
|
||||
return Collections.unmodifiableList(reordered);
|
||||
}
|
||||
|
||||
List<ConfigDataResolutionResult> resolve(ConfigDataLocationResolverContext context, ConfigDataLocation location,
|
||||
Profiles profiles) {
|
||||
List<ConfigDataResolutionResult> resolve(ConfigDataLocationResolverContext context,
|
||||
@Nullable ConfigDataLocation location, @Nullable Profiles profiles) {
|
||||
if (location == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
@@ -98,7 +99,7 @@ class ConfigDataLocationResolvers {
|
||||
}
|
||||
|
||||
private List<ConfigDataResolutionResult> resolve(ConfigDataLocationResolver<?> resolver,
|
||||
ConfigDataLocationResolverContext context, ConfigDataLocation location, Profiles profiles) {
|
||||
ConfigDataLocationResolverContext context, ConfigDataLocation location, @Nullable Profiles profiles) {
|
||||
List<ConfigDataResolutionResult> resolved = resolve(location, false, () -> resolver.resolve(context, location));
|
||||
if (profiles == null) {
|
||||
return resolved;
|
||||
@@ -119,7 +120,7 @@ class ConfigDataLocationResolvers {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> List<T> nonNullList(List<? extends T> list) {
|
||||
private <T> List<T> nonNullList(@Nullable List<? extends T> list) {
|
||||
return (list != null) ? (List<T>) list : Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
+6
-5
@@ -22,6 +22,7 @@ import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.aot.hint.RuntimeHintsRegistrar;
|
||||
@@ -41,7 +42,7 @@ class ConfigDataLocationRuntimeHints implements RuntimeHintsRegistrar {
|
||||
private static final Log logger = LogFactory.getLog(ConfigDataLocationRuntimeHints.class);
|
||||
|
||||
@Override
|
||||
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
|
||||
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
|
||||
List<String> fileNames = getFileNames(classLoader);
|
||||
List<String> locations = getLocations(classLoader);
|
||||
List<String> extensions = getExtensions(classLoader);
|
||||
@@ -60,7 +61,7 @@ class ConfigDataLocationRuntimeHints implements RuntimeHintsRegistrar {
|
||||
* @param classLoader the classloader to use
|
||||
* @return the configuration file names
|
||||
*/
|
||||
protected List<String> getFileNames(ClassLoader classLoader) {
|
||||
protected List<String> getFileNames(@Nullable ClassLoader classLoader) {
|
||||
return Arrays.asList(StandardConfigDataLocationResolver.DEFAULT_CONFIG_NAMES);
|
||||
}
|
||||
|
||||
@@ -70,7 +71,7 @@ class ConfigDataLocationRuntimeHints implements RuntimeHintsRegistrar {
|
||||
* @param classLoader the classloader to use
|
||||
* @return the configuration file locations
|
||||
*/
|
||||
protected List<String> getLocations(ClassLoader classLoader) {
|
||||
protected List<String> getLocations(@Nullable ClassLoader classLoader) {
|
||||
List<String> classpathLocations = new ArrayList<>();
|
||||
for (ConfigDataLocation candidate : ConfigDataEnvironment.DEFAULT_SEARCH_LOCATIONS) {
|
||||
for (ConfigDataLocation configDataLocation : candidate.split()) {
|
||||
@@ -89,7 +90,7 @@ class ConfigDataLocationRuntimeHints implements RuntimeHintsRegistrar {
|
||||
* @param classLoader the classloader to use
|
||||
* @return the configuration file extensions
|
||||
*/
|
||||
protected List<String> getExtensions(ClassLoader classLoader) {
|
||||
protected List<String> getExtensions(@Nullable ClassLoader classLoader) {
|
||||
List<String> extensions = new ArrayList<>();
|
||||
List<PropertySourceLoader> propertySourceLoaders = getSpringFactoriesLoader(classLoader)
|
||||
.load(PropertySourceLoader.class);
|
||||
@@ -104,7 +105,7 @@ class ConfigDataLocationRuntimeHints implements RuntimeHintsRegistrar {
|
||||
return extensions;
|
||||
}
|
||||
|
||||
protected SpringFactoriesLoader getSpringFactoriesLoader(ClassLoader classLoader) {
|
||||
protected SpringFactoriesLoader getSpringFactoriesLoader(@Nullable ClassLoader classLoader) {
|
||||
return SpringFactoriesLoader.forDefaultResourceLocation(classLoader);
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.boot.context.config;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.origin.OriginProvider;
|
||||
|
||||
/**
|
||||
@@ -31,7 +33,7 @@ public abstract class ConfigDataNotFoundException extends ConfigDataException im
|
||||
* @param message the exception message
|
||||
* @param cause the exception cause
|
||||
*/
|
||||
ConfigDataNotFoundException(String message, Throwable cause) {
|
||||
ConfigDataNotFoundException(String message, @Nullable Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.boot.context.config;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.diagnostics.AbstractFailureAnalyzer;
|
||||
import org.springframework.boot.diagnostics.FailureAnalysis;
|
||||
import org.springframework.boot.origin.Origin;
|
||||
@@ -48,7 +50,7 @@ class ConfigDataNotFoundFailureAnalyzer extends AbstractFailureAnalyzer<ConfigDa
|
||||
return new FailureAnalysis(message, action.toString(), cause);
|
||||
}
|
||||
|
||||
private ConfigDataLocation getLocation(ConfigDataNotFoundException cause) {
|
||||
private @Nullable ConfigDataLocation getLocation(ConfigDataNotFoundException cause) {
|
||||
if (cause instanceof ConfigDataLocationNotFoundException locationNotFoundException) {
|
||||
return locationNotFoundException.getLocation();
|
||||
}
|
||||
|
||||
+10
-8
@@ -20,6 +20,8 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.cloud.CloudPlatform;
|
||||
import org.springframework.boot.context.properties.bind.Bindable;
|
||||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
@@ -42,14 +44,14 @@ class ConfigDataProperties {
|
||||
|
||||
private final List<ConfigDataLocation> imports;
|
||||
|
||||
private final Activate activate;
|
||||
private final @Nullable Activate activate;
|
||||
|
||||
/**
|
||||
* Create a new {@link ConfigDataProperties} instance.
|
||||
* @param imports the imports requested
|
||||
* @param activate the activate properties
|
||||
*/
|
||||
ConfigDataProperties(@Name("import") List<ConfigDataLocation> imports, Activate activate) {
|
||||
ConfigDataProperties(@Nullable @Name("import") List<ConfigDataLocation> imports, @Nullable Activate activate) {
|
||||
this.imports = (imports != null) ? imports : Collections.emptyList();
|
||||
this.activate = activate;
|
||||
}
|
||||
@@ -68,7 +70,7 @@ class ConfigDataProperties {
|
||||
* @param activationContext the activation context
|
||||
* @return {@code true} if the config data property source is active
|
||||
*/
|
||||
boolean isActive(ConfigDataActivationContext activationContext) {
|
||||
boolean isActive(@Nullable ConfigDataActivationContext activationContext) {
|
||||
return this.activate == null || this.activate.isActive(activationContext);
|
||||
}
|
||||
|
||||
@@ -86,7 +88,7 @@ class ConfigDataProperties {
|
||||
* @param binder the binder used to bind the properties
|
||||
* @return a {@link ConfigDataProperties} instance or {@code null}
|
||||
*/
|
||||
static ConfigDataProperties get(Binder binder) {
|
||||
static @Nullable ConfigDataProperties get(Binder binder) {
|
||||
return binder.bind(NAME, BINDABLE_PROPERTIES, new ConfigDataLocationBindHandler()).orElse(null);
|
||||
}
|
||||
|
||||
@@ -95,7 +97,7 @@ class ConfigDataProperties {
|
||||
*/
|
||||
static class Activate {
|
||||
|
||||
private final CloudPlatform onCloudPlatform;
|
||||
private final @Nullable CloudPlatform onCloudPlatform;
|
||||
|
||||
private final String[] onProfile;
|
||||
|
||||
@@ -104,7 +106,7 @@ class ConfigDataProperties {
|
||||
* @param onCloudPlatform the cloud platform required for activation
|
||||
* @param onProfile the profile expression required for activation
|
||||
*/
|
||||
Activate(CloudPlatform onCloudPlatform, String[] onProfile) {
|
||||
Activate(@Nullable CloudPlatform onCloudPlatform, String[] onProfile) {
|
||||
this.onProfile = onProfile;
|
||||
this.onCloudPlatform = onCloudPlatform;
|
||||
}
|
||||
@@ -115,7 +117,7 @@ class ConfigDataProperties {
|
||||
* @param activationContext the activation context
|
||||
* @return {@code true} if the config data property source is active
|
||||
*/
|
||||
boolean isActive(ConfigDataActivationContext activationContext) {
|
||||
boolean isActive(@Nullable ConfigDataActivationContext activationContext) {
|
||||
if (activationContext == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -129,7 +131,7 @@ class ConfigDataProperties {
|
||||
return this.onCloudPlatform == null || this.onCloudPlatform == cloudPlatform;
|
||||
}
|
||||
|
||||
private boolean isActive(Profiles profiles) {
|
||||
private boolean isActive(@Nullable Profiles profiles) {
|
||||
return ObjectUtils.isEmpty(this.onProfile)
|
||||
|| (profiles != null && matchesActiveProfiles(profiles::isAccepted));
|
||||
}
|
||||
|
||||
+9
-4
@@ -16,10 +16,15 @@
|
||||
|
||||
package org.springframework.boot.context.config;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.aot.hint.ExecutableMode;
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.aot.hint.RuntimeHintsRegistrar;
|
||||
import org.springframework.boot.context.properties.bind.BindableRuntimeHintsRegistrar;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
@@ -30,11 +35,11 @@ import org.springframework.util.ReflectionUtils;
|
||||
class ConfigDataPropertiesRuntimeHints implements RuntimeHintsRegistrar {
|
||||
|
||||
@Override
|
||||
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
|
||||
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
|
||||
BindableRuntimeHintsRegistrar.forTypes(ConfigDataProperties.class).registerHints(hints);
|
||||
hints.reflection()
|
||||
.registerMethod(ReflectionUtils.findMethod(ConfigDataLocation.class, "of", String.class),
|
||||
ExecutableMode.INVOKE);
|
||||
Method method = ReflectionUtils.findMethod(ConfigDataLocation.class, "of", String.class);
|
||||
Assert.state(method != null, "'method' must not be null");
|
||||
hints.reflection().registerMethod(method, ExecutableMode.INVOKE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+10
-8
@@ -20,6 +20,8 @@ import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.origin.Origin;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -35,7 +37,7 @@ public class ConfigDataResourceNotFoundException extends ConfigDataNotFoundExcep
|
||||
|
||||
private final ConfigDataResource resource;
|
||||
|
||||
private final ConfigDataLocation location;
|
||||
private final @Nullable ConfigDataLocation location;
|
||||
|
||||
/**
|
||||
* Create a new {@link ConfigDataResourceNotFoundException} instance.
|
||||
@@ -50,12 +52,12 @@ public class ConfigDataResourceNotFoundException extends ConfigDataNotFoundExcep
|
||||
* @param resource the resource that could not be found
|
||||
* @param cause the exception cause
|
||||
*/
|
||||
public ConfigDataResourceNotFoundException(ConfigDataResource resource, Throwable cause) {
|
||||
public ConfigDataResourceNotFoundException(ConfigDataResource resource, @Nullable Throwable cause) {
|
||||
this(resource, null, cause);
|
||||
}
|
||||
|
||||
private ConfigDataResourceNotFoundException(ConfigDataResource resource, ConfigDataLocation location,
|
||||
Throwable cause) {
|
||||
private ConfigDataResourceNotFoundException(ConfigDataResource resource, @Nullable ConfigDataLocation location,
|
||||
@Nullable Throwable cause) {
|
||||
super(getMessage(resource, location), cause);
|
||||
Assert.notNull(resource, "'resource' must not be null");
|
||||
this.resource = resource;
|
||||
@@ -74,12 +76,12 @@ public class ConfigDataResourceNotFoundException extends ConfigDataNotFoundExcep
|
||||
* Return the original location that was resolved to determine the resource.
|
||||
* @return the location or {@code null} if no location is available
|
||||
*/
|
||||
public ConfigDataLocation getLocation() {
|
||||
public @Nullable ConfigDataLocation getLocation() {
|
||||
return this.location;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Origin getOrigin() {
|
||||
public @Nullable Origin getOrigin() {
|
||||
return Origin.from(this.location);
|
||||
}
|
||||
|
||||
@@ -97,11 +99,11 @@ public class ConfigDataResourceNotFoundException extends ConfigDataNotFoundExcep
|
||||
return new ConfigDataResourceNotFoundException(this.resource, location, getCause());
|
||||
}
|
||||
|
||||
private static String getMessage(ConfigDataResource resource, ConfigDataLocation location) {
|
||||
private static String getMessage(ConfigDataResource resource, @Nullable ConfigDataLocation location) {
|
||||
return String.format("Config data %s cannot be found", getReferenceDescription(resource, location));
|
||||
}
|
||||
|
||||
private static String getReferenceDescription(ConfigDataResource resource, ConfigDataLocation location) {
|
||||
private static String getReferenceDescription(ConfigDataResource resource, @Nullable ConfigDataLocation location) {
|
||||
String description = String.format("resource '%s'", resource);
|
||||
if (location != null) {
|
||||
description += String.format(" via location '%s'", location);
|
||||
|
||||
+4
-2
@@ -19,6 +19,8 @@ package org.springframework.boot.context.config;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* User-provided hint for an otherwise missing file extension.
|
||||
*
|
||||
@@ -30,9 +32,9 @@ final class FileExtensionHint {
|
||||
|
||||
private static final FileExtensionHint NONE = new FileExtensionHint(null);
|
||||
|
||||
private final Matcher matcher;
|
||||
private final @Nullable Matcher matcher;
|
||||
|
||||
private FileExtensionHint(Matcher matcher) {
|
||||
private FileExtensionHint(@Nullable Matcher matcher) {
|
||||
this.matcher = matcher;
|
||||
}
|
||||
|
||||
|
||||
+12
-8
@@ -16,11 +16,14 @@
|
||||
|
||||
package org.springframework.boot.context.config;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.context.properties.source.ConfigurationProperty;
|
||||
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
|
||||
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
|
||||
import org.springframework.boot.origin.Origin;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Exception thrown when an attempt is made to resolve a property against an inactive
|
||||
@@ -35,11 +38,11 @@ public class InactiveConfigDataAccessException extends ConfigDataException {
|
||||
|
||||
private final PropertySource<?> propertySource;
|
||||
|
||||
private final ConfigDataResource location;
|
||||
private final @Nullable ConfigDataResource location;
|
||||
|
||||
private final String propertyName;
|
||||
|
||||
private final Origin origin;
|
||||
private final @Nullable Origin origin;
|
||||
|
||||
/**
|
||||
* Create a new {@link InactiveConfigDataAccessException} instance.
|
||||
@@ -49,8 +52,8 @@ public class InactiveConfigDataAccessException extends ConfigDataException {
|
||||
* @param propertyName the name of the property
|
||||
* @param origin the origin or the property or {@code null}
|
||||
*/
|
||||
InactiveConfigDataAccessException(PropertySource<?> propertySource, ConfigDataResource location,
|
||||
String propertyName, Origin origin) {
|
||||
InactiveConfigDataAccessException(PropertySource<?> propertySource, @Nullable ConfigDataResource location,
|
||||
String propertyName, @Nullable Origin origin) {
|
||||
super(getMessage(propertySource, location, propertyName, origin), null);
|
||||
this.propertySource = propertySource;
|
||||
this.location = location;
|
||||
@@ -58,8 +61,8 @@ public class InactiveConfigDataAccessException extends ConfigDataException {
|
||||
this.origin = origin;
|
||||
}
|
||||
|
||||
private static String getMessage(PropertySource<?> propertySource, ConfigDataResource location, String propertyName,
|
||||
Origin origin) {
|
||||
private static String getMessage(PropertySource<?> propertySource, @Nullable ConfigDataResource location,
|
||||
String propertyName, @Nullable Origin origin) {
|
||||
StringBuilder message = new StringBuilder("Inactive property source '");
|
||||
message.append(propertySource.getName());
|
||||
if (location != null) {
|
||||
@@ -90,7 +93,7 @@ public class InactiveConfigDataAccessException extends ConfigDataException {
|
||||
* source was not loaded from {@link ConfigData}.
|
||||
* @return the config data location or {@code null}
|
||||
*/
|
||||
public ConfigDataResource getLocation() {
|
||||
public @Nullable ConfigDataResource getLocation() {
|
||||
return this.location;
|
||||
}
|
||||
|
||||
@@ -106,7 +109,7 @@ public class InactiveConfigDataAccessException extends ConfigDataException {
|
||||
* Return the origin or the property or {@code null}.
|
||||
* @return the property origin
|
||||
*/
|
||||
public Origin getOrigin() {
|
||||
public @Nullable Origin getOrigin() {
|
||||
return this.origin;
|
||||
}
|
||||
|
||||
@@ -122,6 +125,7 @@ public class InactiveConfigDataAccessException extends ConfigDataException {
|
||||
if (property != null) {
|
||||
PropertySource<?> propertySource = contributor.getPropertySource();
|
||||
ConfigDataResource location = contributor.getResource();
|
||||
Assert.state(propertySource != null, "'propertySource' must not be null");
|
||||
throw new InactiveConfigDataAccessException(propertySource, location, name.toString(),
|
||||
property.getOrigin());
|
||||
}
|
||||
|
||||
+8
-6
@@ -22,6 +22,8 @@ import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.context.properties.source.ConfigurationProperty;
|
||||
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
|
||||
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
|
||||
@@ -60,12 +62,12 @@ public class InvalidConfigDataPropertyException extends ConfigDataException {
|
||||
|
||||
private final ConfigurationProperty property;
|
||||
|
||||
private final ConfigurationPropertyName replacement;
|
||||
private final @Nullable ConfigurationPropertyName replacement;
|
||||
|
||||
private final ConfigDataResource location;
|
||||
private final @Nullable ConfigDataResource location;
|
||||
|
||||
InvalidConfigDataPropertyException(ConfigurationProperty property, boolean profileSpecific,
|
||||
ConfigurationPropertyName replacement, ConfigDataResource location) {
|
||||
@Nullable ConfigurationPropertyName replacement, @Nullable ConfigDataResource location) {
|
||||
super(getMessage(property, profileSpecific, replacement, location), null);
|
||||
this.property = property;
|
||||
this.replacement = replacement;
|
||||
@@ -85,7 +87,7 @@ public class InvalidConfigDataPropertyException extends ConfigDataException {
|
||||
* the source was not loaded from {@link ConfigData}.
|
||||
* @return the config data location or {@code null}
|
||||
*/
|
||||
public ConfigDataResource getLocation() {
|
||||
public @Nullable ConfigDataResource getLocation() {
|
||||
return this.location;
|
||||
}
|
||||
|
||||
@@ -94,7 +96,7 @@ public class InvalidConfigDataPropertyException extends ConfigDataException {
|
||||
* replacement is available.
|
||||
* @return the replacement property name
|
||||
*/
|
||||
public ConfigurationPropertyName getReplacement() {
|
||||
public @Nullable ConfigurationPropertyName getReplacement() {
|
||||
return this.replacement;
|
||||
}
|
||||
|
||||
@@ -126,7 +128,7 @@ public class InvalidConfigDataPropertyException extends ConfigDataException {
|
||||
}
|
||||
|
||||
private static String getMessage(ConfigurationProperty property, boolean profileSpecific,
|
||||
ConfigurationPropertyName replacement, ConfigDataResource location) {
|
||||
@Nullable ConfigurationPropertyName replacement, @Nullable ConfigDataResource location) {
|
||||
StringBuilder message = new StringBuilder("Property '");
|
||||
message.append(property.getName());
|
||||
if (location != null) {
|
||||
|
||||
+8
-6
@@ -28,6 +28,8 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.context.properties.bind.BindResult;
|
||||
import org.springframework.boot.context.properties.bind.Bindable;
|
||||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
@@ -77,7 +79,7 @@ public class Profiles implements Iterable<String> {
|
||||
* @param binder the binder for profile properties
|
||||
* @param additionalProfiles any additional active profiles
|
||||
*/
|
||||
Profiles(Environment environment, Binder binder, Collection<String> additionalProfiles) {
|
||||
Profiles(Environment environment, Binder binder, @Nullable Collection<String> additionalProfiles) {
|
||||
ProfilesValidator validator = ProfilesValidator.get(binder);
|
||||
if (additionalProfiles != null) {
|
||||
validator.validate(additionalProfiles, () -> "Invalid profile property value found in additional profiles");
|
||||
@@ -89,7 +91,7 @@ public class Profiles implements Iterable<String> {
|
||||
}
|
||||
|
||||
private List<String> getActivatedProfiles(Environment environment, Binder binder, ProfilesValidator validator,
|
||||
Collection<String> additionalProfiles) {
|
||||
@Nullable Collection<String> additionalProfiles) {
|
||||
return asUniqueItemList(getProfiles(environment, binder, validator, Type.ACTIVE), additionalProfiles);
|
||||
}
|
||||
|
||||
@@ -117,7 +119,7 @@ public class Profiles implements Iterable<String> {
|
||||
return boundProfiles.orElse(type.getDefaultValue());
|
||||
}
|
||||
|
||||
private boolean hasProgrammaticallySetProfiles(Type type, String environmentPropertyValue,
|
||||
private boolean hasProgrammaticallySetProfiles(Type type, @Nullable String environmentPropertyValue,
|
||||
Set<String> environmentPropertyProfiles, Set<String> environmentProfiles) {
|
||||
if (!StringUtils.hasLength(environmentPropertyValue)) {
|
||||
return !type.getDefaultValue().equals(environmentProfiles);
|
||||
@@ -134,7 +136,7 @@ public class Profiles implements Iterable<String> {
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<String> expandProfiles(List<String> profiles) {
|
||||
private List<String> expandProfiles(@Nullable List<String> profiles) {
|
||||
Deque<String> stack = new ArrayDeque<>();
|
||||
asReversedList(profiles).forEach(stack::push);
|
||||
Set<String> expandedProfiles = new LinkedHashSet<>();
|
||||
@@ -147,7 +149,7 @@ public class Profiles implements Iterable<String> {
|
||||
return asUniqueItemList(expandedProfiles);
|
||||
}
|
||||
|
||||
private List<String> asReversedList(List<String> list) {
|
||||
private List<String> asReversedList(@Nullable List<String> list) {
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
@@ -160,7 +162,7 @@ public class Profiles implements Iterable<String> {
|
||||
return asUniqueItemList(profiles, null);
|
||||
}
|
||||
|
||||
private List<String> asUniqueItemList(Collection<String> profiles, Collection<String> additional) {
|
||||
private List<String> asUniqueItemList(Collection<String> profiles, @Nullable Collection<String> additional) {
|
||||
LinkedHashSet<String> uniqueItems = new LinkedHashSet<>();
|
||||
if (!CollectionUtils.isEmpty(additional)) {
|
||||
uniqueItems.addAll(additional);
|
||||
|
||||
+3
-1
@@ -22,6 +22,8 @@ import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.context.properties.bind.BindContext;
|
||||
import org.springframework.boot.context.properties.bind.BindHandler;
|
||||
import org.springframework.boot.context.properties.bind.Bindable;
|
||||
@@ -61,7 +63,7 @@ final class ProfilesValidator implements BindHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private void validate(Object value) {
|
||||
private void validate(@Nullable Object value) {
|
||||
if (!this.validate) {
|
||||
return;
|
||||
}
|
||||
|
||||
+12
-7
@@ -30,6 +30,7 @@ import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.context.config.LocationResourceLoader.ResourceType;
|
||||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
@@ -67,7 +68,7 @@ public class StandardConfigDataLocationResolver
|
||||
|
||||
private static final Pattern URL_PREFIX = Pattern.compile("^([a-zA-Z][a-zA-Z0-9*]*?:)(.*$)");
|
||||
|
||||
private static final String NO_PROFILE = null;
|
||||
private static final @Nullable String NO_PROFILE = null;
|
||||
|
||||
private final Log logger;
|
||||
|
||||
@@ -186,7 +187,7 @@ public class StandardConfigDataLocationResolver
|
||||
}
|
||||
|
||||
private Set<StandardConfigDataReference> getReferencesForDirectory(ConfigDataLocation configDataLocation,
|
||||
String directory, String profile) {
|
||||
String directory, @Nullable String profile) {
|
||||
Set<StandardConfigDataReference> references = new LinkedHashSet<>();
|
||||
for (String name : this.configNames) {
|
||||
Deque<StandardConfigDataReference> referencesForName = getReferencesForConfigName(name, configDataLocation,
|
||||
@@ -197,7 +198,7 @@ public class StandardConfigDataLocationResolver
|
||||
}
|
||||
|
||||
private Deque<StandardConfigDataReference> getReferencesForConfigName(String name,
|
||||
ConfigDataLocation configDataLocation, String directory, String profile) {
|
||||
ConfigDataLocation configDataLocation, String directory, @Nullable String profile) {
|
||||
Deque<StandardConfigDataReference> references = new ArrayDeque<>();
|
||||
for (PropertySourceLoader propertySourceLoader : this.propertySourceLoaders) {
|
||||
for (String extension : propertySourceLoader.getFileExtensions()) {
|
||||
@@ -212,7 +213,7 @@ public class StandardConfigDataLocationResolver
|
||||
}
|
||||
|
||||
private Set<StandardConfigDataReference> getReferencesForFile(ConfigDataLocation configDataLocation, String file,
|
||||
String profile) {
|
||||
@Nullable String profile) {
|
||||
FileExtensionHint fileExtensionHint = FileExtensionHint.from(file);
|
||||
if (fileExtensionHint.isPresent()) {
|
||||
file = FileExtensionHint.removeFrom(file) + fileExtensionHint;
|
||||
@@ -242,7 +243,7 @@ public class StandardConfigDataLocationResolver
|
||||
+ "check the location prefix if a different resolver is expected");
|
||||
}
|
||||
|
||||
private String getLoadableFileExtension(PropertySourceLoader loader, String file) {
|
||||
private @Nullable String getLoadableFileExtension(PropertySourceLoader loader, String file) {
|
||||
for (String fileExtension : loader.getFileExtensions()) {
|
||||
if (StringUtils.endsWithIgnoreCase(file, fileExtension)) {
|
||||
return fileExtension;
|
||||
@@ -285,13 +286,17 @@ public class StandardConfigDataLocationResolver
|
||||
}
|
||||
|
||||
private Set<StandardConfigDataResource> resolveNonPatternEmptyDirectories(StandardConfigDataReference reference) {
|
||||
Resource resource = this.resourceLoader.getResource(reference.getDirectory());
|
||||
String directory = reference.getDirectory();
|
||||
Assert.state(directory != null, "'directory' must not be null");
|
||||
Resource resource = this.resourceLoader.getResource(directory);
|
||||
return (resource instanceof ClassPathResource || !resource.exists()) ? Collections.emptySet()
|
||||
: Collections.singleton(new StandardConfigDataResource(reference, resource, true));
|
||||
}
|
||||
|
||||
private Set<StandardConfigDataResource> resolvePatternEmptyDirectories(StandardConfigDataReference reference) {
|
||||
Resource[] subdirectories = this.resourceLoader.getResources(reference.getDirectory(), ResourceType.DIRECTORY);
|
||||
String directory = reference.getDirectory();
|
||||
Assert.state(directory != null, "'directory' must not be null");
|
||||
Resource[] subdirectories = this.resourceLoader.getResources(directory, ResourceType.DIRECTORY);
|
||||
ConfigDataLocation location = reference.getConfigDataLocation();
|
||||
if (!location.isOptional() && ObjectUtils.isEmpty(subdirectories)) {
|
||||
String message = String.format("Config data location '%s' contains no subdirectories", location);
|
||||
|
||||
+8
-6
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.boot.context.config;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.env.PropertySourceLoader;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -31,9 +33,9 @@ class StandardConfigDataReference {
|
||||
|
||||
private final String resourceLocation;
|
||||
|
||||
private final String directory;
|
||||
private final @Nullable String directory;
|
||||
|
||||
private final String profile;
|
||||
private final @Nullable String profile;
|
||||
|
||||
private final PropertySourceLoader propertySourceLoader;
|
||||
|
||||
@@ -48,8 +50,8 @@ class StandardConfigDataReference {
|
||||
* @param propertySourceLoader the property source loader that should be used for this
|
||||
* reference
|
||||
*/
|
||||
StandardConfigDataReference(ConfigDataLocation configDataLocation, String directory, String root, String profile,
|
||||
String extension, PropertySourceLoader propertySourceLoader) {
|
||||
StandardConfigDataReference(ConfigDataLocation configDataLocation, @Nullable String directory, String root,
|
||||
@Nullable String profile, @Nullable String extension, PropertySourceLoader propertySourceLoader) {
|
||||
this.configDataLocation = configDataLocation;
|
||||
String profileSuffix = (StringUtils.hasText(profile)) ? "-" + profile : "";
|
||||
this.resourceLocation = root + profileSuffix + ((extension != null) ? "." + extension : "");
|
||||
@@ -70,11 +72,11 @@ class StandardConfigDataReference {
|
||||
return !this.configDataLocation.isOptional() && this.directory != null;
|
||||
}
|
||||
|
||||
String getDirectory() {
|
||||
@Nullable String getDirectory() {
|
||||
return this.directory;
|
||||
}
|
||||
|
||||
String getProfile() {
|
||||
@Nullable String getProfile() {
|
||||
return this.profile;
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -19,6 +19,8 @@ package org.springframework.boot.context.config;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.core.io.FileUrlResource;
|
||||
@@ -81,7 +83,7 @@ public class StandardConfigDataResource extends ConfigDataResource {
|
||||
* @return the profile or {@code null}
|
||||
* @since 2.4.6
|
||||
*/
|
||||
public String getProfile() {
|
||||
public @Nullable String getProfile() {
|
||||
return this.reference.getProfile();
|
||||
}
|
||||
|
||||
@@ -105,7 +107,7 @@ public class StandardConfigDataResource extends ConfigDataResource {
|
||||
return ours.equals(other) || isSameFile(getUnderlyingFile(ours), getUnderlyingFile(other));
|
||||
}
|
||||
|
||||
private boolean isSameFile(File ours, File other) {
|
||||
private boolean isSameFile(@Nullable File ours, @Nullable File other) {
|
||||
return (ours != null) && ours.equals(other);
|
||||
}
|
||||
|
||||
@@ -128,7 +130,7 @@ public class StandardConfigDataResource extends ConfigDataResource {
|
||||
return this.resource.toString();
|
||||
}
|
||||
|
||||
private File getUnderlyingFile(Resource resource) {
|
||||
private @Nullable File getUnderlyingFile(Resource resource) {
|
||||
try {
|
||||
if (resource instanceof ClassPathResource || resource instanceof FileSystemResource
|
||||
|| resource instanceof FileUrlResource) {
|
||||
|
||||
+4
-2
@@ -20,6 +20,8 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.env.PropertySourceLoader;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
|
||||
@@ -38,7 +40,7 @@ class SystemEnvironmentConfigDataLocationResolver
|
||||
|
||||
private final List<PropertySourceLoader> loaders;
|
||||
|
||||
private final Function<String, String> environment;
|
||||
private final Function<String, @Nullable String> environment;
|
||||
|
||||
SystemEnvironmentConfigDataLocationResolver() {
|
||||
this.loaders = SpringFactoriesLoader.loadFactories(PropertySourceLoader.class, getClass().getClassLoader());
|
||||
@@ -46,7 +48,7 @@ class SystemEnvironmentConfigDataLocationResolver
|
||||
}
|
||||
|
||||
SystemEnvironmentConfigDataLocationResolver(List<PropertySourceLoader> loaders,
|
||||
Function<String, String> environment) {
|
||||
Function<String, @Nullable String> environment) {
|
||||
this.loaders = loaders;
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
+5
-3
@@ -22,6 +22,8 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.env.PropertySourceLoader;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
@@ -39,10 +41,10 @@ class SystemEnvironmentConfigDataResource extends ConfigDataResource {
|
||||
|
||||
private final PropertySourceLoader loader;
|
||||
|
||||
private final Function<String, String> environment;
|
||||
private final Function<String, @Nullable String> environment;
|
||||
|
||||
SystemEnvironmentConfigDataResource(String variableName, PropertySourceLoader loader,
|
||||
Function<String, String> environment) {
|
||||
Function<String, @Nullable String> environment) {
|
||||
this.variableName = variableName;
|
||||
this.loader = loader;
|
||||
this.environment = environment;
|
||||
@@ -56,7 +58,7 @@ class SystemEnvironmentConfigDataResource extends ConfigDataResource {
|
||||
return this.loader;
|
||||
}
|
||||
|
||||
List<PropertySource<?>> load() throws IOException {
|
||||
@Nullable List<PropertySource<?>> load() throws IOException {
|
||||
String content = this.environment.apply(this.variableName);
|
||||
return (content != null) ? this.loader.load(StringUtils.capitalize(toString()), asResource(content)) : null;
|
||||
}
|
||||
|
||||
+3
@@ -20,4 +20,7 @@
|
||||
*
|
||||
* @see org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.boot.context.config;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
+7
-5
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.boot.context.event;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
||||
@@ -29,7 +31,7 @@ import org.springframework.context.ConfigurableApplicationContext;
|
||||
@SuppressWarnings("serial")
|
||||
public class ApplicationFailedEvent extends SpringApplicationEvent {
|
||||
|
||||
private final ConfigurableApplicationContext context;
|
||||
private final @Nullable ConfigurableApplicationContext context;
|
||||
|
||||
private final Throwable exception;
|
||||
|
||||
@@ -40,8 +42,8 @@ public class ApplicationFailedEvent extends SpringApplicationEvent {
|
||||
* @param context the context that was being created (maybe null)
|
||||
* @param exception the exception that caused the error
|
||||
*/
|
||||
public ApplicationFailedEvent(SpringApplication application, String[] args, ConfigurableApplicationContext context,
|
||||
Throwable exception) {
|
||||
public ApplicationFailedEvent(SpringApplication application, String[] args,
|
||||
@Nullable ConfigurableApplicationContext context, Throwable exception) {
|
||||
super(application, args);
|
||||
this.context = context;
|
||||
this.exception = exception;
|
||||
@@ -49,9 +51,9 @@ public class ApplicationFailedEvent extends SpringApplicationEvent {
|
||||
|
||||
/**
|
||||
* Return the application context.
|
||||
* @return the context
|
||||
* @return the context or {@code null}
|
||||
*/
|
||||
public ConfigurableApplicationContext getApplicationContext() {
|
||||
public @Nullable ConfigurableApplicationContext getApplicationContext() {
|
||||
return this.context;
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -18,6 +18,8 @@ package org.springframework.boot.context.event;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
||||
@@ -37,7 +39,7 @@ public class ApplicationReadyEvent extends SpringApplicationEvent {
|
||||
|
||||
private final ConfigurableApplicationContext context;
|
||||
|
||||
private final Duration timeTaken;
|
||||
private final @Nullable Duration timeTaken;
|
||||
|
||||
/**
|
||||
* Create a new {@link ApplicationReadyEvent} instance.
|
||||
@@ -48,7 +50,7 @@ public class ApplicationReadyEvent extends SpringApplicationEvent {
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public ApplicationReadyEvent(SpringApplication application, String[] args, ConfigurableApplicationContext context,
|
||||
Duration timeTaken) {
|
||||
@Nullable Duration timeTaken) {
|
||||
super(application, args);
|
||||
this.context = context;
|
||||
this.timeTaken = timeTaken;
|
||||
@@ -68,7 +70,7 @@ public class ApplicationReadyEvent extends SpringApplicationEvent {
|
||||
* @return the time taken to be ready to service requests
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public Duration getTimeTaken() {
|
||||
public @Nullable Duration getTimeTaken() {
|
||||
return this.timeTaken;
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -18,6 +18,8 @@ package org.springframework.boot.context.event;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
@@ -36,7 +38,7 @@ public class ApplicationStartedEvent extends SpringApplicationEvent {
|
||||
|
||||
private final ConfigurableApplicationContext context;
|
||||
|
||||
private final Duration timeTaken;
|
||||
private final @Nullable Duration timeTaken;
|
||||
|
||||
/**
|
||||
* Create a new {@link ApplicationStartedEvent} instance.
|
||||
@@ -47,7 +49,7 @@ public class ApplicationStartedEvent extends SpringApplicationEvent {
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public ApplicationStartedEvent(SpringApplication application, String[] args, ConfigurableApplicationContext context,
|
||||
Duration timeTaken) {
|
||||
@Nullable Duration timeTaken) {
|
||||
super(application, args);
|
||||
this.context = context;
|
||||
this.timeTaken = timeTaken;
|
||||
@@ -66,7 +68,7 @@ public class ApplicationStartedEvent extends SpringApplicationEvent {
|
||||
* @return the startup time
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public Duration getTimeTaken() {
|
||||
public @Nullable Duration getTimeTaken() {
|
||||
return this.timeTaken;
|
||||
}
|
||||
|
||||
|
||||
+4
-3
@@ -20,6 +20,7 @@ import java.time.Duration;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.ConfigurableBootstrapContext;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
@@ -99,19 +100,19 @@ class EventPublishingRunListener implements SpringApplicationRunListener, Ordere
|
||||
}
|
||||
|
||||
@Override
|
||||
public void started(ConfigurableApplicationContext context, Duration timeTaken) {
|
||||
public void started(ConfigurableApplicationContext context, @Nullable Duration timeTaken) {
|
||||
context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context, timeTaken));
|
||||
AvailabilityChangeEvent.publish(context, LivenessState.CORRECT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ready(ConfigurableApplicationContext context, Duration timeTaken) {
|
||||
public void ready(ConfigurableApplicationContext context, @Nullable Duration timeTaken) {
|
||||
context.publishEvent(new ApplicationReadyEvent(this.application, this.args, context, timeTaken));
|
||||
AvailabilityChangeEvent.publish(context, ReadinessState.ACCEPTING_TRAFFIC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(ConfigurableApplicationContext context, Throwable exception) {
|
||||
public void failed(@Nullable ConfigurableApplicationContext context, Throwable exception) {
|
||||
ApplicationFailedEvent event = new ApplicationFailedEvent(this.application, this.args, context, exception);
|
||||
if (context != null && context.isActive()) {
|
||||
// Listeners have been registered to the application context so we should
|
||||
|
||||
+3
@@ -18,4 +18,7 @@
|
||||
* {@link org.springframework.context.ApplicationEvent ApplicationEvents} triggered by
|
||||
* Spring Boot.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.boot.context.event;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
+13
-8
@@ -25,6 +25,7 @@ import java.util.function.BiConsumer;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
@@ -54,6 +55,7 @@ import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.log.LogMessage;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -181,17 +183,17 @@ public class LoggingApplicationListener implements GenericApplicationListener {
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private LoggingSystem loggingSystem;
|
||||
private @Nullable LoggingSystem loggingSystem;
|
||||
|
||||
private LogFile logFile;
|
||||
private @Nullable LogFile logFile;
|
||||
|
||||
private LoggerGroups loggerGroups;
|
||||
private @Nullable LoggerGroups loggerGroups;
|
||||
|
||||
private int order = DEFAULT_ORDER;
|
||||
|
||||
private boolean parseArgs = true;
|
||||
|
||||
private LogLevel springBootLogging = null;
|
||||
private @Nullable LogLevel springBootLogging = null;
|
||||
|
||||
@Override
|
||||
public boolean supportsEventType(ResolvableType resolvableType) {
|
||||
@@ -199,11 +201,11 @@ public class LoggingApplicationListener implements GenericApplicationListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsSourceType(Class<?> sourceType) {
|
||||
public boolean supportsSourceType(@Nullable Class<?> sourceType) {
|
||||
return isAssignableFrom(sourceType, SOURCE_TYPES);
|
||||
}
|
||||
|
||||
private boolean isAssignableFrom(Class<?> type, Class<?>... supportedTypes) {
|
||||
private boolean isAssignableFrom(@Nullable Class<?> type, Class<?>... supportedTypes) {
|
||||
if (type != null) {
|
||||
for (Class<?> supportedType : supportedTypes) {
|
||||
if (supportedType.isAssignableFrom(type)) {
|
||||
@@ -250,6 +252,7 @@ public class LoggingApplicationListener implements GenericApplicationListener {
|
||||
ConfigurableApplicationContext applicationContext = event.getApplicationContext();
|
||||
ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
|
||||
if (!beanFactory.containsBean(LOGGING_SYSTEM_BEAN_NAME)) {
|
||||
Assert.state(this.loggingSystem != null, "loggingSystem is not set");
|
||||
beanFactory.registerSingleton(LOGGING_SYSTEM_BEAN_NAME, this.loggingSystem);
|
||||
}
|
||||
if (this.logFile != null && !beanFactory.containsBean(LOG_FILE_BEAN_NAME)) {
|
||||
@@ -295,6 +298,7 @@ public class LoggingApplicationListener implements GenericApplicationListener {
|
||||
}
|
||||
this.loggerGroups = new LoggerGroups(DEFAULT_GROUP_LOGGERS);
|
||||
initializeEarlyLoggingLevel(environment);
|
||||
Assert.state(this.loggingSystem != null, "loggingSystem is not set");
|
||||
initializeSystem(environment, this.loggingSystem, this.logFile);
|
||||
initializeFinalLoggingLevels(environment, this.loggingSystem);
|
||||
registerShutdownHookIfNecessary(environment, this.loggingSystem);
|
||||
@@ -321,7 +325,8 @@ public class LoggingApplicationListener implements GenericApplicationListener {
|
||||
return (value != null && !value.equals("false"));
|
||||
}
|
||||
|
||||
private void initializeSystem(ConfigurableEnvironment environment, LoggingSystem system, LogFile logFile) {
|
||||
private void initializeSystem(ConfigurableEnvironment environment, LoggingSystem system,
|
||||
@Nullable LogFile logFile) {
|
||||
String logConfig = environment.getProperty(CONFIG_PROPERTY);
|
||||
if (StringUtils.hasLength(logConfig)) {
|
||||
logConfig = logConfig.strip();
|
||||
@@ -348,7 +353,7 @@ public class LoggingApplicationListener implements GenericApplicationListener {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean ignoreLogConfig(String logConfig) {
|
||||
private boolean ignoreLogConfig(@Nullable String logConfig) {
|
||||
return !StringUtils.hasLength(logConfig) || logConfig.startsWith("-D");
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -17,4 +17,7 @@
|
||||
/**
|
||||
* Logging integration with Spring's Application Context.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.boot.context.logging;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
+6
-4
@@ -24,6 +24,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.metrics.StartupStep;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -41,7 +43,7 @@ class BufferedStartupStep implements StartupStep {
|
||||
|
||||
private final long id;
|
||||
|
||||
private final BufferedStartupStep parent;
|
||||
private final @Nullable BufferedStartupStep parent;
|
||||
|
||||
private final List<Tag> tags = new ArrayList<>();
|
||||
|
||||
@@ -51,7 +53,7 @@ class BufferedStartupStep implements StartupStep {
|
||||
|
||||
private final AtomicBoolean ended = new AtomicBoolean();
|
||||
|
||||
BufferedStartupStep(BufferedStartupStep parent, String name, long id, Instant startTime,
|
||||
BufferedStartupStep(@Nullable BufferedStartupStep parent, String name, long id, Instant startTime,
|
||||
Consumer<BufferedStartupStep> recorder) {
|
||||
this.parent = parent;
|
||||
this.name = name;
|
||||
@@ -60,7 +62,7 @@ class BufferedStartupStep implements StartupStep {
|
||||
this.recorder = recorder;
|
||||
}
|
||||
|
||||
BufferedStartupStep getParent() {
|
||||
@Nullable BufferedStartupStep getParent() {
|
||||
return this.parent;
|
||||
}
|
||||
|
||||
@@ -79,7 +81,7 @@ class BufferedStartupStep implements StartupStep {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getParentId() {
|
||||
public @Nullable Long getParentId() {
|
||||
return (this.parent != null) ? this.parent.getId() : null;
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -26,6 +26,8 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.context.metrics.buffering.StartupTimeline.TimelineEvent;
|
||||
import org.springframework.core.metrics.ApplicationStartup;
|
||||
import org.springframework.core.metrics.StartupStep;
|
||||
@@ -133,7 +135,7 @@ public class BufferingApplicationStartup implements ApplicationStartup {
|
||||
}
|
||||
}
|
||||
|
||||
private BufferedStartupStep getLatestActive(BufferedStartupStep step) {
|
||||
private @Nullable BufferedStartupStep getLatestActive(@Nullable BufferedStartupStep step) {
|
||||
while (step != null && step.isEnded()) {
|
||||
step = step.getParent();
|
||||
}
|
||||
|
||||
+3
@@ -18,4 +18,7 @@
|
||||
* {@link org.springframework.core.metrics.ApplicationStartup} implementation for
|
||||
* buffering steps and measuring their processing time.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.boot.context.metrics.buffering;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@@ -17,4 +17,7 @@
|
||||
/**
|
||||
* Classes related to Spring's {@link org.springframework.context.ApplicationContext}.
|
||||
*/
|
||||
@NullMarked
|
||||
package org.springframework.boot.context;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
+6
-4
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.boot.context.properties;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.boot.context.properties.bind.BindMethod;
|
||||
@@ -36,21 +38,21 @@ final class BindMethodAttribute {
|
||||
private BindMethodAttribute() {
|
||||
}
|
||||
|
||||
static BindMethod get(ApplicationContext applicationContext, String beanName) {
|
||||
static @Nullable BindMethod get(ApplicationContext applicationContext, String beanName) {
|
||||
return (applicationContext instanceof ConfigurableApplicationContext configurableApplicationContext)
|
||||
? get(configurableApplicationContext.getBeanFactory(), beanName) : null;
|
||||
}
|
||||
|
||||
static BindMethod get(ConfigurableListableBeanFactory beanFactory, String beanName) {
|
||||
static @Nullable BindMethod get(ConfigurableListableBeanFactory beanFactory, String beanName) {
|
||||
return (!beanFactory.containsBeanDefinition(beanName)) ? null : get(beanFactory.getBeanDefinition(beanName));
|
||||
}
|
||||
|
||||
static BindMethod get(BeanDefinitionRegistry beanDefinitionRegistry, String beanName) {
|
||||
static @Nullable BindMethod get(BeanDefinitionRegistry beanDefinitionRegistry, String beanName) {
|
||||
return (!beanDefinitionRegistry.containsBeanDefinition(beanName)) ? null
|
||||
: get(beanDefinitionRegistry.getBeanDefinition(beanName));
|
||||
}
|
||||
|
||||
static BindMethod get(AttributeAccessor attributes) {
|
||||
static @Nullable BindMethod get(AttributeAccessor attributes) {
|
||||
return (BindMethod) attributes.getAttribute(NAME);
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -20,6 +20,8 @@ import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
@@ -53,7 +55,7 @@ public class BoundConfigurationProperties {
|
||||
* @param name the property name
|
||||
* @return the bound property or {@code null}
|
||||
*/
|
||||
public ConfigurationProperty get(ConfigurationPropertyName name) {
|
||||
public @Nullable ConfigurationProperty get(ConfigurationPropertyName name) {
|
||||
return this.properties.get(name);
|
||||
}
|
||||
|
||||
@@ -71,7 +73,7 @@ public class BoundConfigurationProperties {
|
||||
* @param context the context to search
|
||||
* @return a {@link BoundConfigurationProperties} or {@code null}
|
||||
*/
|
||||
public static BoundConfigurationProperties get(ApplicationContext context) {
|
||||
public static @Nullable BoundConfigurationProperties get(ApplicationContext context) {
|
||||
return (!context.containsBeanDefinition(BEAN_NAME)) ? null
|
||||
: context.getBean(BEAN_NAME, BoundConfigurationProperties.class);
|
||||
}
|
||||
|
||||
+29
-16
@@ -24,6 +24,8 @@ import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
@@ -40,6 +42,7 @@ import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.annotation.MergedAnnotation;
|
||||
import org.springframework.core.annotation.MergedAnnotations;
|
||||
import org.springframework.core.annotation.MergedAnnotations.SearchStrategy;
|
||||
import org.springframework.lang.Contract;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
@@ -66,11 +69,11 @@ public final class ConfigurationPropertiesBean {
|
||||
|
||||
private final String name;
|
||||
|
||||
private final Object instance;
|
||||
private final @Nullable Object instance;
|
||||
|
||||
private final Bindable<?> bindTarget;
|
||||
|
||||
private ConfigurationPropertiesBean(String name, Object instance, Bindable<?> bindTarget) {
|
||||
private ConfigurationPropertiesBean(String name, @Nullable Object instance, Bindable<?> bindTarget) {
|
||||
this.name = name;
|
||||
this.instance = instance;
|
||||
this.bindTarget = bindTarget;
|
||||
@@ -88,7 +91,7 @@ public final class ConfigurationPropertiesBean {
|
||||
* Return the actual Spring bean instance.
|
||||
* @return the bean instance
|
||||
*/
|
||||
public Object getInstance() {
|
||||
public @Nullable Object getInstance() {
|
||||
return this.instance;
|
||||
}
|
||||
|
||||
@@ -97,7 +100,9 @@ public final class ConfigurationPropertiesBean {
|
||||
* @return the bean type
|
||||
*/
|
||||
Class<?> getType() {
|
||||
return this.bindTarget.getType().resolve();
|
||||
Class<?> resolved = this.bindTarget.getType().resolve();
|
||||
Assert.state(resolved != null, "'resolved' must not be null");
|
||||
return resolved;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,7 +112,9 @@ public final class ConfigurationPropertiesBean {
|
||||
* @return the configuration properties annotation
|
||||
*/
|
||||
public ConfigurationProperties getAnnotation() {
|
||||
return this.bindTarget.getAnnotation(ConfigurationProperties.class);
|
||||
ConfigurationProperties annotation = this.bindTarget.getAnnotation(ConfigurationProperties.class);
|
||||
Assert.state(annotation != null, "'annotation' must not be null");
|
||||
return annotation;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -193,7 +200,8 @@ public final class ConfigurationPropertiesBean {
|
||||
* factory method are annotated with
|
||||
* {@link ConfigurationProperties @ConfigurationProperties}
|
||||
*/
|
||||
public static ConfigurationPropertiesBean get(ApplicationContext applicationContext, Object bean, String beanName) {
|
||||
public static @Nullable ConfigurationPropertiesBean get(ApplicationContext applicationContext, Object bean,
|
||||
String beanName) {
|
||||
Method factoryMethod = findFactoryMethod(applicationContext, beanName);
|
||||
Bindable<Object> bindTarget = createBindTarget(bean, bean.getClass(), factoryMethod);
|
||||
if (bindTarget == null) {
|
||||
@@ -209,18 +217,19 @@ public final class ConfigurationPropertiesBean {
|
||||
return create(beanName, bean, bindTarget);
|
||||
}
|
||||
|
||||
private static Method findFactoryMethod(ApplicationContext applicationContext, String beanName) {
|
||||
private static @Nullable Method findFactoryMethod(ApplicationContext applicationContext, String beanName) {
|
||||
if (applicationContext instanceof ConfigurableApplicationContext configurableContext) {
|
||||
return findFactoryMethod(configurableContext, beanName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Method findFactoryMethod(ConfigurableApplicationContext applicationContext, String beanName) {
|
||||
private static @Nullable Method findFactoryMethod(ConfigurableApplicationContext applicationContext,
|
||||
String beanName) {
|
||||
return findFactoryMethod(applicationContext.getBeanFactory(), beanName);
|
||||
}
|
||||
|
||||
private static Method findFactoryMethod(ConfigurableListableBeanFactory beanFactory, String beanName) {
|
||||
private static @Nullable Method findFactoryMethod(ConfigurableListableBeanFactory beanFactory, String beanName) {
|
||||
if (beanFactory.containsBeanDefinition(beanName)) {
|
||||
BeanDefinition beanDefinition = beanFactory.getMergedBeanDefinition(beanName);
|
||||
if (beanDefinition instanceof RootBeanDefinition rootBeanDefinition) {
|
||||
@@ -237,14 +246,16 @@ public final class ConfigurationPropertiesBean {
|
||||
return create(beanName, null, bindTarget.withBindMethod(VALUE_OBJECT_BIND_METHOD));
|
||||
}
|
||||
|
||||
private static Bindable<Object> createBindTarget(Object bean, Class<?> beanType, Method factoryMethod) {
|
||||
private static @Nullable Bindable<Object> createBindTarget(@Nullable Object bean, Class<?> beanType,
|
||||
@Nullable Method factoryMethod) {
|
||||
ResolvableType type = (factoryMethod != null) ? ResolvableType.forMethodReturnType(factoryMethod)
|
||||
: ResolvableType.forClass(beanType);
|
||||
Annotation[] annotations = findAnnotations(bean, beanType, factoryMethod);
|
||||
return (annotations != null) ? Bindable.of(type).withAnnotations(annotations) : null;
|
||||
}
|
||||
|
||||
private static Annotation[] findAnnotations(Object instance, Class<?> type, Method factory) {
|
||||
private static Annotation @Nullable [] findAnnotations(@Nullable Object instance, Class<?> type,
|
||||
@Nullable Method factory) {
|
||||
ConfigurationProperties annotation = findAnnotation(instance, type, factory, ConfigurationProperties.class);
|
||||
if (annotation == null) {
|
||||
return null;
|
||||
@@ -253,8 +264,8 @@ public final class ConfigurationPropertiesBean {
|
||||
return (validated != null) ? new Annotation[] { annotation, validated } : new Annotation[] { annotation };
|
||||
}
|
||||
|
||||
private static <A extends Annotation> A findAnnotation(Object instance, Class<?> type, Method factory,
|
||||
Class<A> annotationType) {
|
||||
private static <A extends Annotation> @Nullable A findAnnotation(@Nullable Object instance, Class<?> type,
|
||||
@Nullable Method factory, Class<A> annotationType) {
|
||||
MergedAnnotation<A> annotation = MergedAnnotation.missing();
|
||||
if (factory != null) {
|
||||
annotation = findMergedAnnotation(factory, annotationType);
|
||||
@@ -269,13 +280,15 @@ public final class ConfigurationPropertiesBean {
|
||||
return annotation.isPresent() ? annotation.synthesize() : null;
|
||||
}
|
||||
|
||||
private static <A extends Annotation> MergedAnnotation<A> findMergedAnnotation(AnnotatedElement element,
|
||||
private static <A extends Annotation> MergedAnnotation<A> findMergedAnnotation(@Nullable AnnotatedElement element,
|
||||
Class<A> annotationType) {
|
||||
return (element != null) ? MergedAnnotations.from(element, SearchStrategy.TYPE_HIERARCHY).get(annotationType)
|
||||
: MergedAnnotation.missing();
|
||||
}
|
||||
|
||||
private static ConfigurationPropertiesBean create(String name, Object instance, Bindable<Object> bindTarget) {
|
||||
@Contract("_, _, !null -> !null")
|
||||
private static @Nullable ConfigurationPropertiesBean create(String name, @Nullable Object instance,
|
||||
@Nullable Bindable<Object> bindTarget) {
|
||||
return (bindTarget != null) ? new ConfigurationPropertiesBean(name, instance, bindTarget) : null;
|
||||
}
|
||||
|
||||
@@ -298,7 +311,7 @@ public final class ConfigurationPropertiesBean {
|
||||
}
|
||||
|
||||
private static org.springframework.boot.context.properties.bind.BindMethod deduceBindMethod(
|
||||
Constructor<?> bindConstructor) {
|
||||
@Nullable Constructor<?> bindConstructor) {
|
||||
return (bindConstructor != null) ? VALUE_OBJECT_BIND_METHOD : JAVA_BEAN_BIND_METHOD;
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -19,6 +19,8 @@ package org.springframework.boot.context.properties;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.aot.generate.GenerationContext;
|
||||
import org.springframework.beans.factory.aot.BeanFactoryInitializationAotContribution;
|
||||
import org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor;
|
||||
@@ -41,7 +43,7 @@ import org.springframework.util.ClassUtils;
|
||||
class ConfigurationPropertiesBeanFactoryInitializationAotProcessor implements BeanFactoryInitializationAotProcessor {
|
||||
|
||||
@Override
|
||||
public ConfigurationPropertiesReflectionHintsContribution processAheadOfTime(
|
||||
public @Nullable ConfigurationPropertiesReflectionHintsContribution processAheadOfTime(
|
||||
ConfigurableListableBeanFactory beanFactory) {
|
||||
String[] beanNames = beanFactory.getBeanNamesForAnnotation(ConfigurationProperties.class);
|
||||
List<Bindable<?>> bindables = new ArrayList<>();
|
||||
|
||||
+3
-1
@@ -20,6 +20,8 @@ import java.util.function.Predicate;
|
||||
|
||||
import javax.lang.model.element.Modifier;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.aot.generate.GeneratedMethod;
|
||||
import org.springframework.aot.generate.GenerationContext;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
@@ -45,7 +47,7 @@ import org.springframework.javapoet.CodeBlock;
|
||||
class ConfigurationPropertiesBeanRegistrationAotProcessor implements BeanRegistrationAotProcessor {
|
||||
|
||||
@Override
|
||||
public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) {
|
||||
public @Nullable BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) {
|
||||
if (!isImmutableConfigurationPropertiesBeanDefinition(registeredBean.getMergedBeanDefinition())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
+14
-10
@@ -20,6 +20,8 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.PropertyEditorRegistry;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
@@ -72,13 +74,13 @@ class ConfigurationPropertiesBinder {
|
||||
|
||||
private final PropertySources propertySources;
|
||||
|
||||
private final Validator configurationPropertiesValidator;
|
||||
private final @Nullable Validator configurationPropertiesValidator;
|
||||
|
||||
private final boolean jsr303Present;
|
||||
|
||||
private volatile List<ConfigurationPropertiesBindHandlerAdvisor> bindHandlerAdvisors;
|
||||
private volatile @Nullable List<ConfigurationPropertiesBindHandlerAdvisor> bindHandlerAdvisors;
|
||||
|
||||
private volatile Binder binder;
|
||||
private volatile @Nullable Binder binder;
|
||||
|
||||
ConfigurationPropertiesBinder(ApplicationContext applicationContext) {
|
||||
this.applicationContext = applicationContext;
|
||||
@@ -101,7 +103,7 @@ class ConfigurationPropertiesBinder {
|
||||
return getBinder().bindOrCreate(annotation.prefix(), target, bindHandler);
|
||||
}
|
||||
|
||||
private Validator getConfigurationPropertiesValidator(ApplicationContext applicationContext) {
|
||||
private @Nullable Validator getConfigurationPropertiesValidator(ApplicationContext applicationContext) {
|
||||
if (applicationContext.containsBean(VALIDATOR_BEAN_NAME)) {
|
||||
return applicationContext.getBean(VALIDATOR_BEAN_NAME, Validator.class);
|
||||
}
|
||||
@@ -153,7 +155,9 @@ class ConfigurationPropertiesBinder {
|
||||
validators.add(this.configurationPropertiesValidator);
|
||||
}
|
||||
if (this.jsr303Present && target.getAnnotation(Validated.class) != null) {
|
||||
validators.add(getJsr303Validator(target.getType().resolve()));
|
||||
Class<?> resolved = target.getType().resolve();
|
||||
Assert.state(resolved != null, "'resolved' must not be null");
|
||||
validators.add(getJsr303Validator(resolved));
|
||||
}
|
||||
Validator selfValidator = getSelfValidator(target);
|
||||
if (selfValidator != null) {
|
||||
@@ -162,7 +166,7 @@ class ConfigurationPropertiesBinder {
|
||||
return validators;
|
||||
}
|
||||
|
||||
private Validator getSelfValidator(Bindable<?> target) {
|
||||
private @Nullable Validator getSelfValidator(Bindable<?> target) {
|
||||
if (target.getValue() != null) {
|
||||
Object value = target.getValue().get();
|
||||
return (value instanceof Validator validator) ? validator : null;
|
||||
@@ -194,11 +198,11 @@ class ConfigurationPropertiesBinder {
|
||||
return new PropertySourcesPlaceholdersResolver(this.propertySources);
|
||||
}
|
||||
|
||||
private List<ConversionService> getConversionServices() {
|
||||
private @Nullable List<ConversionService> getConversionServices() {
|
||||
return new ConversionServiceDeducer(this.applicationContext).getConversionServices();
|
||||
}
|
||||
|
||||
private Consumer<PropertyEditorRegistry> getPropertyEditorInitializer() {
|
||||
private @Nullable Consumer<PropertyEditorRegistry> getPropertyEditorInitializer() {
|
||||
if (this.applicationContext instanceof ConfigurableApplicationContext configurableContext) {
|
||||
return configurableContext.getBeanFactory()::copyRegisteredEditorsTo;
|
||||
}
|
||||
@@ -235,7 +239,7 @@ class ConfigurationPropertiesBinder {
|
||||
? target.withBindRestrictions(BindRestriction.NO_DIRECT_PROPERTY) : target;
|
||||
}
|
||||
|
||||
private boolean isConfigurationProperties(Class<?> target) {
|
||||
private boolean isConfigurationProperties(@Nullable Class<?> target) {
|
||||
return target != null && MergedAnnotations.from(target).isPresent(ConfigurationProperties.class);
|
||||
}
|
||||
|
||||
@@ -247,7 +251,7 @@ class ConfigurationPropertiesBinder {
|
||||
static class ConfigurationPropertiesBinderFactory
|
||||
implements FactoryBean<ConfigurationPropertiesBinder>, ApplicationContextAware {
|
||||
|
||||
private ConfigurationPropertiesBinder binder;
|
||||
private @Nullable ConfigurationPropertiesBinder binder;
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
|
||||
+6
-1
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.boot.context.properties;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
@@ -49,10 +51,13 @@ public class ConfigurationPropertiesBindingPostProcessor
|
||||
*/
|
||||
public static final String BEAN_NAME = ConfigurationPropertiesBindingPostProcessor.class.getName();
|
||||
|
||||
@SuppressWarnings("NullAway.Init")
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@SuppressWarnings("NullAway.Init")
|
||||
private BeanDefinitionRegistry registry;
|
||||
|
||||
@SuppressWarnings("NullAway.Init")
|
||||
private ConfigurationPropertiesBinder binder;
|
||||
|
||||
@Override
|
||||
@@ -85,7 +90,7 @@ public class ConfigurationPropertiesBindingPostProcessor
|
||||
return BindMethod.VALUE_OBJECT.equals(BindMethodAttribute.get(this.registry, beanName));
|
||||
}
|
||||
|
||||
private void bind(ConfigurationPropertiesBean bean) {
|
||||
private void bind(@Nullable ConfigurationPropertiesBean bean) {
|
||||
if (bean == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
+6
-1
@@ -19,6 +19,8 @@ package org.springframework.boot.context.properties;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.convert.ApplicationConversionService;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
@@ -96,7 +98,10 @@ final class ConfigurationPropertiesCharSequenceToObjectConverter implements Cond
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
public @Nullable Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
return this.conversionService.convert(source.toString(), STRING, targetType);
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user