diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java index 026a804a73..05778c30c8 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java @@ -74,6 +74,7 @@ import org.springframework.core.env.StandardEnvironment; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.support.SpringFactoriesLoader; +import org.springframework.core.io.support.SpringFactoriesLoader.ArgumentResolver; import org.springframework.core.metrics.ApplicationStartup; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -437,21 +438,19 @@ public class SpringApplication { } private SpringApplicationRunListeners getRunListeners(String[] args) { - SpringFactoriesLoader.ArgumentResolver argumentResolver = SpringFactoriesLoader.ArgumentResolver - .of(SpringApplication.class, this).and(String[].class, args); - return new SpringApplicationRunListeners(logger, - getSpringFactoriesInstances(SpringApplicationRunListener.class, argumentResolver), - this.applicationStartup); + ArgumentResolver argumentResolver = ArgumentResolver.of(SpringApplication.class, this); + argumentResolver = argumentResolver.and(String[].class, args); + Collection listeners = getSpringFactoriesInstances( + SpringApplicationRunListener.class, argumentResolver); + return new SpringApplicationRunListeners(logger, listeners, this.applicationStartup); } private Collection getSpringFactoriesInstances(Class type) { return getSpringFactoriesInstances(type, null); } - private Collection getSpringFactoriesInstances(Class type, - SpringFactoriesLoader.ArgumentResolver argumentResolver) { - ClassLoader classLoader = getClassLoader(); - return SpringFactoriesLoader.forDefaultResourceLocation(classLoader).load(type, argumentResolver); + private Collection getSpringFactoriesInstances(Class type, ArgumentResolver argumentResolver) { + return SpringFactoriesLoader.forDefaultResourceLocation(getClassLoader()).load(type, argumentResolver); } private ConfigurableEnvironment getOrCreateEnvironment() { @@ -802,8 +801,7 @@ public class SpringApplication { private Collection getExceptionReporters(ConfigurableApplicationContext context) { try { - SpringFactoriesLoader.ArgumentResolver argumentResolver = SpringFactoriesLoader.ArgumentResolver - .of(ConfigurableApplicationContext.class, context); + ArgumentResolver argumentResolver = ArgumentResolver.of(ConfigurableApplicationContext.class, context); return getSpringFactoriesInstances(SpringBootExceptionReporter.class, argumentResolver); } catch (Throwable ex) { diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataLoaders.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataLoaders.java index 1f93a0b2be..b8b696f94a 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataLoaders.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataLoaders.java @@ -29,6 +29,7 @@ import org.springframework.boot.ConfigurableBootstrapContext; import org.springframework.boot.logging.DeferredLogFactory; import org.springframework.core.ResolvableType; import org.springframework.core.io.support.SpringFactoriesLoader; +import org.springframework.core.io.support.SpringFactoriesLoader.ArgumentResolver; import org.springframework.core.log.LogMessage; import org.springframework.util.Assert; @@ -56,9 +57,13 @@ class ConfigDataLoaders { ConfigDataLoaders(DeferredLogFactory logFactory, ConfigurableBootstrapContext bootstrapContext, SpringFactoriesLoader springFactoriesLoader) { this.logger = logFactory.getLog(getClass()); - SpringFactoriesLoader.ArgumentResolver argumentResolver = SpringFactoriesLoader.ArgumentResolver - .of(DeferredLogFactory.class, logFactory).and(ConfigurableBootstrapContext.class, bootstrapContext) - .and(BootstrapContext.class, bootstrapContext).and(BootstrapRegistry.class, bootstrapContext); + ArgumentResolver argumentResolver = ArgumentResolver.of(DeferredLogFactory.class, logFactory); + argumentResolver = argumentResolver.and(ConfigurableBootstrapContext.class, bootstrapContext); + argumentResolver = argumentResolver.and(BootstrapContext.class, bootstrapContext); + argumentResolver = argumentResolver.and(BootstrapRegistry.class, bootstrapContext); + argumentResolver = argumentResolver.andSupplied(Log.class, () -> { + throw new IllegalArgumentException("Log types cannot be injected, please use DeferredLogFactory"); + }); this.loaders = springFactoriesLoader.load(ConfigDataLoader.class, argumentResolver); this.resourceTypes = getResourceTypes(this.loaders); } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataLocationResolvers.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataLocationResolvers.java index c48f404c43..3a1a7709ec 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataLocationResolvers.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigDataLocationResolvers.java @@ -31,6 +31,7 @@ import org.springframework.boot.logging.DeferredLogFactory; import org.springframework.core.env.Environment; import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.support.SpringFactoriesLoader; +import org.springframework.core.io.support.SpringFactoriesLoader.ArgumentResolver; /** * A collection of {@link ConfigDataLocationResolver} instances loaded via @@ -53,10 +54,15 @@ class ConfigDataLocationResolvers { */ ConfigDataLocationResolvers(DeferredLogFactory logFactory, ConfigurableBootstrapContext bootstrapContext, Binder binder, ResourceLoader resourceLoader, SpringFactoriesLoader springFactoriesLoader) { - SpringFactoriesLoader.ArgumentResolver argumentResolver = SpringFactoriesLoader.ArgumentResolver - .of(DeferredLogFactory.class, logFactory).and(Binder.class, binder) - .and(ResourceLoader.class, resourceLoader).and(ConfigurableBootstrapContext.class, bootstrapContext) - .and(BootstrapContext.class, bootstrapContext).and(BootstrapRegistry.class, bootstrapContext); + ArgumentResolver argumentResolver = ArgumentResolver.of(DeferredLogFactory.class, logFactory); + argumentResolver = argumentResolver.and(Binder.class, binder); + argumentResolver = argumentResolver.and(ResourceLoader.class, resourceLoader); + argumentResolver = argumentResolver.and(ConfigurableBootstrapContext.class, bootstrapContext); + argumentResolver = argumentResolver.and(BootstrapContext.class, bootstrapContext); + argumentResolver = argumentResolver.and(BootstrapRegistry.class, bootstrapContext); + argumentResolver = argumentResolver.andSupplied(Log.class, () -> { + throw new IllegalArgumentException("Log types cannot be injected, please use DeferredLogFactory"); + }); this.resolvers = reorder(springFactoriesLoader.load(ConfigDataLocationResolver.class, argumentResolver)); } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/diagnostics/FailureAnalyzers.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/diagnostics/FailureAnalyzers.java index 6af6c73a71..09abc25851 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/diagnostics/FailureAnalyzers.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/diagnostics/FailureAnalyzers.java @@ -67,11 +67,8 @@ final class FailureAnalyzers implements SpringBootExceptionReporter { private static List loadFailureAnalyzers(ConfigurableApplicationContext context, SpringFactoriesLoader springFactoriesLoader) { - ArgumentResolver argumentResolver = (context != null) ? ArgumentResolver - .of(BeanFactory.class, context.getBeanFactory()).and(Environment.class, context.getEnvironment()) - : null; - List analyzers = springFactoriesLoader.load(FailureAnalyzer.class, argumentResolver, - FailureHandler.logging(logger)); + List analyzers = springFactoriesLoader.load(FailureAnalyzer.class, + getArgumentResolver(context), FailureHandler.logging(logger)); List awareAnalyzers = analyzers.stream() .filter((analyzer) -> analyzer instanceof BeanFactoryAware || analyzer instanceof EnvironmentAware) .toList(); @@ -101,6 +98,15 @@ final class FailureAnalyzers implements SpringBootExceptionReporter { return analyzers; } + private static ArgumentResolver getArgumentResolver(ConfigurableApplicationContext context) { + if (context == null) { + return null; + } + ArgumentResolver argumentResolver = ArgumentResolver.of(BeanFactory.class, context.getBeanFactory()); + argumentResolver = argumentResolver.and(Environment.class, context.getEnvironment()); + return argumentResolver; + } + @Override public boolean reportException(Throwable failure) { FailureAnalysis analysis = analyze(failure, this.analyzers); diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/env/SpringFactoriesEnvironmentPostProcessorsFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/env/SpringFactoriesEnvironmentPostProcessorsFactory.java index 19879020a1..932c3f5f6f 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/env/SpringFactoriesEnvironmentPostProcessorsFactory.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/env/SpringFactoriesEnvironmentPostProcessorsFactory.java @@ -23,6 +23,7 @@ import org.springframework.boot.BootstrapRegistry; import org.springframework.boot.ConfigurableBootstrapContext; import org.springframework.boot.logging.DeferredLogFactory; import org.springframework.core.io.support.SpringFactoriesLoader; +import org.springframework.core.io.support.SpringFactoriesLoader.ArgumentResolver; /** * An {@link EnvironmentPostProcessorsFactory} that uses {@link SpringFactoriesLoader}. @@ -40,9 +41,10 @@ class SpringFactoriesEnvironmentPostProcessorsFactory implements EnvironmentPost @Override public List getEnvironmentPostProcessors(DeferredLogFactory logFactory, ConfigurableBootstrapContext bootstrapContext) { - SpringFactoriesLoader.ArgumentResolver argumentResolver = SpringFactoriesLoader.ArgumentResolver - .of(DeferredLogFactory.class, logFactory).and(ConfigurableBootstrapContext.class, bootstrapContext) - .and(BootstrapContext.class, bootstrapContext).and(BootstrapRegistry.class, bootstrapContext); + ArgumentResolver argumentResolver = ArgumentResolver.of(DeferredLogFactory.class, logFactory); + argumentResolver = argumentResolver.and(ConfigurableBootstrapContext.class, bootstrapContext); + argumentResolver = argumentResolver.and(BootstrapContext.class, bootstrapContext); + argumentResolver = argumentResolver.and(BootstrapRegistry.class, bootstrapContext); return this.loader.load(EnvironmentPostProcessor.class, argumentResolver); } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/sql/init/dependency/DatabaseInitializationDependencyConfigurer.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/sql/init/dependency/DatabaseInitializationDependencyConfigurer.java index ae9d002f9b..b86c408ff4 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/sql/init/dependency/DatabaseInitializationDependencyConfigurer.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/sql/init/dependency/DatabaseInitializationDependencyConfigurer.java @@ -39,6 +39,7 @@ import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.Ordered; import org.springframework.core.env.Environment; import org.springframework.core.io.support.SpringFactoriesLoader; +import org.springframework.core.io.support.SpringFactoriesLoader.ArgumentResolver; import org.springframework.core.type.AnnotationMetadata; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; @@ -150,8 +151,7 @@ public class DatabaseInitializationDependencyConfigurer implements ImportBeanDef } private List getDetectors(ConfigurableListableBeanFactory beanFactory, Class type) { - SpringFactoriesLoader.ArgumentResolver argumentResolver = SpringFactoriesLoader.ArgumentResolver - .of(Environment.class, this.environment); + ArgumentResolver argumentResolver = ArgumentResolver.of(Environment.class, this.environment); return SpringFactoriesLoader.forDefaultResourceLocation(beanFactory.getBeanClassLoader()).load(type, argumentResolver); } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigDataLoadersTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigDataLoadersTests.java index fdf0901319..7b48e7ff2a 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigDataLoadersTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigDataLoadersTests.java @@ -22,6 +22,7 @@ import java.util.Arrays; import java.util.List; import java.util.function.Supplier; +import org.apache.commons.logging.Log; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -36,6 +37,7 @@ import org.springframework.core.env.PropertySource; import org.springframework.mock.env.MockPropertySource; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.mockito.Mockito.mock; @@ -72,6 +74,16 @@ class ConfigDataLoadersTests { assertThat(loader.getLogFactory()).isSameAs(this.logFactory); } + @Test + void createWhenLoaderHasLogParameterThrowsException() throws Exception { + MockSpringFactoriesLoader springFactoriesLoader = new MockSpringFactoriesLoader(); + springFactoriesLoader.add(ConfigDataLoader.class, LogConfigDataLoader.class); + assertThatIllegalArgumentException() + .isThrownBy(() -> new ConfigDataLoaders(this.logFactory, this.bootstrapContext, springFactoriesLoader)) + .havingCause().isInstanceOf(IllegalArgumentException.class) + .withMessageContaining("use DeferredLogFactory"); + } + @Test void createWhenLoaderHasBootstrapParametersInjectsBootstrapContext() { MockSpringFactoriesLoader springFactoriesLoader = new MockSpringFactoriesLoader(); @@ -175,6 +187,21 @@ class ConfigDataLoadersTests { } + static class LogConfigDataLoader implements ConfigDataLoader { + + final Log logger; + + LogConfigDataLoader(Log logger) { + this.logger = logger; + } + + @Override + public ConfigData load(ConfigDataLoaderContext context, ConfigDataResource resource) throws IOException { + throw new AssertionError("Unexpected call"); + } + + } + static class BootstrappingConfigDataLoader implements ConfigDataLoader { BootstrappingConfigDataLoader(ConfigurableBootstrapContext configurableBootstrapContext,