Polish SpringFactories ArgumentResolver code

Update `ArgumentResolver` setup to use one statement per line
and throw an exception if `Log` parameter types are present.
pull/30984/head
Phillip Webb 3 years ago
parent 69a88b1938
commit 693941c2c2

@ -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<SpringApplicationRunListener> listeners = getSpringFactoriesInstances(
SpringApplicationRunListener.class, argumentResolver);
return new SpringApplicationRunListeners(logger, listeners, this.applicationStartup);
}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
return getSpringFactoriesInstances(type, null);
}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
SpringFactoriesLoader.ArgumentResolver argumentResolver) {
ClassLoader classLoader = getClassLoader();
return SpringFactoriesLoader.forDefaultResourceLocation(classLoader).load(type, argumentResolver);
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, ArgumentResolver argumentResolver) {
return SpringFactoriesLoader.forDefaultResourceLocation(getClassLoader()).load(type, argumentResolver);
}
private ConfigurableEnvironment getOrCreateEnvironment() {
@ -802,8 +801,7 @@ public class SpringApplication {
private Collection<SpringBootExceptionReporter> 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) {

@ -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);
}

@ -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));
}

@ -67,11 +67,8 @@ final class FailureAnalyzers implements SpringBootExceptionReporter {
private static List<FailureAnalyzer> loadFailureAnalyzers(ConfigurableApplicationContext context,
SpringFactoriesLoader springFactoriesLoader) {
ArgumentResolver argumentResolver = (context != null) ? ArgumentResolver
.of(BeanFactory.class, context.getBeanFactory()).and(Environment.class, context.getEnvironment())
: null;
List<FailureAnalyzer> analyzers = springFactoriesLoader.load(FailureAnalyzer.class, argumentResolver,
FailureHandler.logging(logger));
List<FailureAnalyzer> analyzers = springFactoriesLoader.load(FailureAnalyzer.class,
getArgumentResolver(context), FailureHandler.logging(logger));
List<FailureAnalyzer> 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);

@ -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<EnvironmentPostProcessor> 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);
}

@ -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 <T> List<T> getDetectors(ConfigurableListableBeanFactory beanFactory, Class<T> 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);
}

@ -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<ConfigDataResource> {
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<ConfigDataResource> {
BootstrappingConfigDataLoader(ConfigurableBootstrapContext configurableBootstrapContext,

Loading…
Cancel
Save