Use more flexible SpringFactoriesLoader
Closes gh-30235 Co-authored-by: Madhura Bhave <bhavem@vmware.com> Co-authored-by: Stephane Nicoll <snicoll@vmware.com>
This commit is contained in:
parent
0fbfb8ef09
commit
770cb840c3
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -64,7 +64,7 @@ public class ConditionEvaluationReportLoggingListener
|
|||
this(LogLevel.DEBUG);
|
||||
}
|
||||
|
||||
public ConditionEvaluationReportLoggingListener(LogLevel logLevelForReport) {
|
||||
private ConditionEvaluationReportLoggingListener(LogLevel logLevelForReport) {
|
||||
Assert.isTrue(isInfoOrDebug(logLevelForReport), "LogLevel must be INFO or DEBUG");
|
||||
this.logLevelForReport = logLevelForReport;
|
||||
}
|
||||
|
|
@ -73,6 +73,18 @@ public class ConditionEvaluationReportLoggingListener
|
|||
return LogLevel.INFO.equals(logLevelForReport) || LogLevel.DEBUG.equals(logLevelForReport);
|
||||
}
|
||||
|
||||
/**
|
||||
* Static factory method that creates a
|
||||
* {@link ConditionEvaluationReportLoggingListener} which logs the report at the
|
||||
* specified log level.
|
||||
* @param logLevelForReport the log level to log the report at
|
||||
* @return a {@link ConditionEvaluationReportLoggingListener} instance.
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static ConditionEvaluationReportLoggingListener forLogLevel(LogLevel logLevelForReport) {
|
||||
return new ConditionEvaluationReportLoggingListener(logLevelForReport);
|
||||
}
|
||||
|
||||
public LogLevel getLogLevelForReport() {
|
||||
return this.logLevelForReport;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ class BatchAutoConfigurationWithoutJpaTests {
|
|||
void jdbcWithDefaultSettings() {
|
||||
this.contextRunner.withUserConfiguration(DefaultConfiguration.class, EmbeddedDataSourceConfiguration.class)
|
||||
.withPropertyValues("spring.datasource.generate-unique-name=true")
|
||||
.withInitializer(new ConditionEvaluationReportLoggingListener(LogLevel.INFO)).run((context) -> {
|
||||
.withInitializer(ConditionEvaluationReportLoggingListener.forLogLevel(LogLevel.INFO)).run((context) -> {
|
||||
assertThat(context).hasSingleBean(JobLauncher.class);
|
||||
assertThat(context).hasSingleBean(JobExplorer.class);
|
||||
assertThat(context).hasSingleBean(JobRepository.class);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -123,8 +123,8 @@ class ConditionEvaluationReportLoggingListenerTests {
|
|||
@Test
|
||||
void listenerWithInfoLevelShouldLogAtInfo(CapturedOutput output) {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
ConditionEvaluationReportLoggingListener initializer = new ConditionEvaluationReportLoggingListener(
|
||||
LogLevel.INFO);
|
||||
ConditionEvaluationReportLoggingListener initializer = ConditionEvaluationReportLoggingListener
|
||||
.forLogLevel(LogLevel.INFO);
|
||||
initializer.initialize(context);
|
||||
context.register(Config.class);
|
||||
context.refresh();
|
||||
|
|
@ -135,7 +135,7 @@ class ConditionEvaluationReportLoggingListenerTests {
|
|||
@Test
|
||||
void listenerSupportsOnlyInfoAndDebug() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new ConditionEvaluationReportLoggingListener(LogLevel.TRACE))
|
||||
.isThrownBy(() -> ConditionEvaluationReportLoggingListener.forLogLevel(LogLevel.TRACE))
|
||||
.withMessageContaining("LogLevel must be INFO or DEBUG");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ class SqlInitializationAutoConfigurationTests {
|
|||
@Test
|
||||
void whenConnectionFactoryIsAvailableAndModeIsNeverThenInitializerIsNotAutoConfigured() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(R2dbcAutoConfiguration.class))
|
||||
.withInitializer(new ConditionEvaluationReportLoggingListener(LogLevel.INFO))
|
||||
.withInitializer(ConditionEvaluationReportLoggingListener.forLogLevel(LogLevel.INFO))
|
||||
.withPropertyValues("spring.sql.init.mode:never")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(AbstractScriptDatabaseInitializer.class));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -72,8 +72,8 @@ public final class RemoteSpringApplication {
|
|||
private Collection<ApplicationListener<?>> getListeners() {
|
||||
List<ApplicationListener<?>> listeners = new ArrayList<>();
|
||||
listeners.add(new AnsiOutputApplicationListener());
|
||||
listeners.add(new EnvironmentPostProcessorApplicationListener(
|
||||
EnvironmentPostProcessorsFactory.of(ConfigDataEnvironmentPostProcessor.class)));
|
||||
listeners.add(EnvironmentPostProcessorApplicationListener
|
||||
.with(EnvironmentPostProcessorsFactory.of(ConfigDataEnvironmentPostProcessor.class)));
|
||||
listeners.add(new LoggingApplicationListener());
|
||||
listeners.add(new RemoteUrlPropertyExtractor());
|
||||
return listeners;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -28,7 +28,7 @@ class MyConditionEvaluationReportingTests {
|
|||
void autoConfigTest() {
|
||||
// @formatter:off
|
||||
new ApplicationContextRunner()
|
||||
.withInitializer(new ConditionEvaluationReportLoggingListener(LogLevel.INFO))
|
||||
.withInitializer(ConditionEvaluationReportLoggingListener.forLogLevel(LogLevel.INFO))
|
||||
.run((context) -> {
|
||||
// Test something...
|
||||
});
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class MyConditionEvaluationReportingTests {
|
|||
@Test
|
||||
fun autoConfigTest() {
|
||||
ApplicationContextRunner()
|
||||
.withInitializer(ConditionEvaluationReportLoggingListener(LogLevel.INFO))
|
||||
.withInitializer(ConditionEvaluationReportLoggingListener.forLogLevel(LogLevel.INFO))
|
||||
.run { context: AssertableApplicationContext? -> }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.testsupport.mock;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
|
||||
/**
|
||||
* Simple mock {@link SpringFactoriesLoader} implementation that can be used for testing
|
||||
* purposes.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public class MockSpringFactoriesLoader extends SpringFactoriesLoader {
|
||||
|
||||
private final AtomicInteger sequence = new AtomicInteger();
|
||||
|
||||
private final Map<String, List<String>> factories;
|
||||
|
||||
private final Map<String, Object> implementations = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Create a new {@link MockSpringFactoriesLoader} instance with the default
|
||||
* classloader.
|
||||
*/
|
||||
public MockSpringFactoriesLoader() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link MockSpringFactoriesLoader} instance with the given classloader.
|
||||
* @param classLoader the classloader to use
|
||||
*/
|
||||
public MockSpringFactoriesLoader(ClassLoader classLoader) {
|
||||
this(classLoader, new LinkedHashMap<>());
|
||||
}
|
||||
|
||||
protected MockSpringFactoriesLoader(ClassLoader classLoader, Map<String, List<String>> factories) {
|
||||
super(classLoader, factories);
|
||||
this.factories = factories;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T> T instantiateFactory(String implementationName, Class<T> type, ArgumentResolver argumentResolver,
|
||||
FailureHandler failureHandler) {
|
||||
if (implementationName.startsWith("!")) {
|
||||
Object implementation = this.implementations.get(implementationName);
|
||||
if (implementation != null) {
|
||||
return (T) implementation;
|
||||
}
|
||||
}
|
||||
return super.instantiateFactory(implementationName, type, argumentResolver, failureHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add factory implementations to this instance.
|
||||
* @param factoryType the factory type class
|
||||
* @param factoryImplementations the implementation classes
|
||||
* @param <T> the factory type
|
||||
*/
|
||||
@SafeVarargs
|
||||
public final <T> void add(Class<T> factoryType, Class<? extends T>... factoryImplementations) {
|
||||
for (Class<? extends T> factoryImplementation : factoryImplementations) {
|
||||
add(factoryType.getName(), factoryImplementation.getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add factory implementations to this instance.
|
||||
* @param factoryType the factory type class name
|
||||
* @param factoryImplementations the implementation class names
|
||||
*/
|
||||
public void add(String factoryType, String... factoryImplementations) {
|
||||
List<String> implementations = this.factories.computeIfAbsent(factoryType, (key) -> new ArrayList<>());
|
||||
for (String factoryImplementation : factoryImplementations) {
|
||||
implementations.add(factoryImplementation);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add factory instances to this instance.
|
||||
* @param factoryType the factory type class
|
||||
* @param factoryInstances the implementation instances to add
|
||||
* @param <T> the factory type
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> void addInstance(Class<T> factoryType, T... factoryInstances) {
|
||||
addInstance(factoryType.getName(), factoryInstances);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add factory instances to this instance.
|
||||
* @param factoryType the factory type class name
|
||||
* @param factoryInstance the implementation instances to add
|
||||
* @param <T> the factory instance type
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> void addInstance(String factoryType, T... factoryInstance) {
|
||||
List<String> implementations = this.factories.computeIfAbsent(factoryType, (key) -> new ArrayList<>());
|
||||
for (T factoryImplementation : factoryInstance) {
|
||||
String reference = "!" + factoryType + ":" + factoryImplementation.getClass().getName()
|
||||
+ this.sequence.getAndIncrement();
|
||||
implementations.add(reference);
|
||||
this.implementations.put(reference, factoryImplementation);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package org.springframework.boot;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
|
@ -33,7 +32,6 @@ import java.util.stream.Collectors;
|
|||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.CachedIntrospectionResults;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
|
|
@ -420,42 +418,21 @@ public class SpringApplication {
|
|||
}
|
||||
|
||||
private SpringApplicationRunListeners getRunListeners(String[] args) {
|
||||
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
|
||||
SpringFactoriesLoader.ArgumentResolver argumentResolver = SpringFactoriesLoader.ArgumentResolver
|
||||
.of(SpringApplication.class, this).and(String[].class, args);
|
||||
return new SpringApplicationRunListeners(logger,
|
||||
getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args),
|
||||
getSpringFactoriesInstances(SpringApplicationRunListener.class, argumentResolver),
|
||||
this.applicationStartup);
|
||||
}
|
||||
|
||||
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
|
||||
return getSpringFactoriesInstances(type, new Class<?>[] {});
|
||||
return getSpringFactoriesInstances(type, null);
|
||||
}
|
||||
|
||||
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
|
||||
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
|
||||
SpringFactoriesLoader.ArgumentResolver argumentResolver) {
|
||||
ClassLoader classLoader = getClassLoader();
|
||||
// Use names and ensure unique to protect against duplicates
|
||||
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
|
||||
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
|
||||
AnnotationAwareOrderComparator.sort(instances);
|
||||
return instances;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,
|
||||
ClassLoader classLoader, Object[] args, Set<String> names) {
|
||||
List<T> instances = new ArrayList<>(names.size());
|
||||
for (String name : names) {
|
||||
try {
|
||||
Class<?> instanceClass = ClassUtils.forName(name, classLoader);
|
||||
Assert.isAssignable(type, instanceClass);
|
||||
Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
|
||||
T instance = (T) BeanUtils.instantiateClass(constructor, args);
|
||||
instances.add(instance);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);
|
||||
}
|
||||
}
|
||||
return instances;
|
||||
return SpringFactoriesLoader.forDefaultResourceLocation(classLoader).load(type, argumentResolver);
|
||||
}
|
||||
|
||||
private ConfigurableEnvironment getOrCreateEnvironment() {
|
||||
|
|
@ -806,8 +783,9 @@ public class SpringApplication {
|
|||
|
||||
private Collection<SpringBootExceptionReporter> getExceptionReporters(ConfigurableApplicationContext context) {
|
||||
try {
|
||||
return getSpringFactoriesInstances(SpringBootExceptionReporter.class,
|
||||
new Class<?>[] { ConfigurableApplicationContext.class }, context);
|
||||
SpringFactoriesLoader.ArgumentResolver argumentResolver = SpringFactoriesLoader.ArgumentResolver
|
||||
.of(ConfigurableApplicationContext.class, context);
|
||||
return getSpringFactoriesInstances(SpringBootExceptionReporter.class, argumentResolver);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
return Collections.emptyList();
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import org.springframework.boot.context.config.ConfigDataEnvironmentPostProcesso
|
|||
import org.springframework.boot.env.EnvironmentPostProcessor;
|
||||
import org.springframework.boot.json.JsonParser;
|
||||
import org.springframework.boot.json.JsonParserFactory;
|
||||
import org.springframework.boot.logging.DeferredLogFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.env.CommandLinePropertySource;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
|
|
@ -101,10 +102,11 @@ public class CloudFoundryVcapEnvironmentPostProcessor implements EnvironmentPost
|
|||
|
||||
/**
|
||||
* Create a new {@link CloudFoundryVcapEnvironmentPostProcessor} instance.
|
||||
* @param logger the logger to use
|
||||
* @param logFactory the log factory to use
|
||||
* @since 3.0
|
||||
*/
|
||||
public CloudFoundryVcapEnvironmentPostProcessor(Log logger) {
|
||||
this.logger = logger;
|
||||
public CloudFoundryVcapEnvironmentPostProcessor(DeferredLogFactory logFactory) {
|
||||
this.logger = logFactory.getLog(CloudFoundryVcapEnvironmentPostProcessor.class);
|
||||
}
|
||||
|
||||
public void setOrder(int order) {
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ import org.springframework.core.env.Environment;
|
|||
import org.springframework.core.env.MutablePropertySources;
|
||||
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.StringUtils;
|
||||
|
||||
|
|
@ -148,13 +149,15 @@ class ConfigDataEnvironment {
|
|||
this.additionalProfiles = additionalProfiles;
|
||||
this.environmentUpdateListener = (environmentUpdateListener != null) ? environmentUpdateListener
|
||||
: ConfigDataEnvironmentUpdateListener.NONE;
|
||||
this.loaders = new ConfigDataLoaders(logFactory, bootstrapContext, resourceLoader.getClassLoader());
|
||||
this.loaders = new ConfigDataLoaders(logFactory, bootstrapContext,
|
||||
SpringFactoriesLoader.forDefaultResourceLocation());
|
||||
this.contributors = createContributors(binder);
|
||||
}
|
||||
|
||||
protected ConfigDataLocationResolvers createConfigDataLocationResolvers(DeferredLogFactory logFactory,
|
||||
ConfigurableBootstrapContext bootstrapContext, Binder binder, ResourceLoader resourceLoader) {
|
||||
return new ConfigDataLocationResolvers(logFactory, bootstrapContext, binder, resourceLoader);
|
||||
return new ConfigDataLocationResolvers(logFactory, bootstrapContext, binder, resourceLoader,
|
||||
SpringFactoriesLoader.forDefaultResourceLocation(resourceLoader.getClassLoader()));
|
||||
}
|
||||
|
||||
private ConfigDataEnvironmentContributors createContributors(Binder binder) {
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces
|
|||
this(logFactory, bootstrapContext, null);
|
||||
}
|
||||
|
||||
public ConfigDataEnvironmentPostProcessor(DeferredLogFactory logFactory,
|
||||
private ConfigDataEnvironmentPostProcessor(DeferredLogFactory logFactory,
|
||||
ConfigurableBootstrapContext bootstrapContext,
|
||||
ConfigDataEnvironmentUpdateListener environmentUpdateListener) {
|
||||
this.logFactory = logFactory;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -18,8 +18,6 @@ package org.springframework.boot.context.config;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import org.springframework.boot.BootstrapContext;
|
||||
import org.springframework.boot.BootstrapRegistry;
|
||||
import org.springframework.boot.ConfigurableBootstrapContext;
|
||||
|
|
@ -30,8 +28,7 @@ import org.springframework.boot.logging.DeferredLogFactory;
|
|||
* {@link ConfigDataResource}. Implementations should be added as {@code spring.factories}
|
||||
* entries. The following constructor parameter types are supported:
|
||||
* <ul>
|
||||
* <li>{@link Log} or {@link DeferredLogFactory} - if the loader needs deferred
|
||||
* logging</li>
|
||||
* <li>{@link DeferredLogFactory} - if the loader needs deferred logging</li>
|
||||
* <li>{@link ConfigurableBootstrapContext} - A bootstrap context that can be used to
|
||||
* store objects that may be expensive to create, or need to be shared
|
||||
* ({@link BootstrapContext} or {@link BootstrapRegistry} may also be used).</li>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -27,7 +27,6 @@ import org.springframework.boot.BootstrapContext;
|
|||
import org.springframework.boot.BootstrapRegistry;
|
||||
import org.springframework.boot.ConfigurableBootstrapContext;
|
||||
import org.springframework.boot.logging.DeferredLogFactory;
|
||||
import org.springframework.boot.util.Instantiator;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
import org.springframework.core.log.LogMessage;
|
||||
|
|
@ -43,7 +42,8 @@ class ConfigDataLoaders {
|
|||
|
||||
private final Log logger;
|
||||
|
||||
private final List<ConfigDataLoader<?>> loaders;
|
||||
@SuppressWarnings("rawtypes")
|
||||
private final List<ConfigDataLoader> loaders;
|
||||
|
||||
private final List<Class<?>> resourceTypes;
|
||||
|
||||
|
|
@ -51,37 +51,20 @@ class ConfigDataLoaders {
|
|||
* Create a new {@link ConfigDataLoaders} instance.
|
||||
* @param logFactory the deferred log factory
|
||||
* @param bootstrapContext the bootstrap context
|
||||
* @param classLoader the class loader used when loading
|
||||
* @param springFactoriesLoader the loader to use
|
||||
*/
|
||||
ConfigDataLoaders(DeferredLogFactory logFactory, ConfigurableBootstrapContext bootstrapContext,
|
||||
ClassLoader classLoader) {
|
||||
this(logFactory, bootstrapContext, classLoader,
|
||||
SpringFactoriesLoader.loadFactoryNames(ConfigDataLoader.class, classLoader));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link ConfigDataLoaders} instance.
|
||||
* @param logFactory the deferred log factory
|
||||
* @param bootstrapContext the bootstrap context
|
||||
* @param classLoader the class loader used when loading
|
||||
* @param names the {@link ConfigDataLoader} class names instantiate
|
||||
*/
|
||||
ConfigDataLoaders(DeferredLogFactory logFactory, ConfigurableBootstrapContext bootstrapContext,
|
||||
ClassLoader classLoader, List<String> names) {
|
||||
SpringFactoriesLoader springFactoriesLoader) {
|
||||
this.logger = logFactory.getLog(getClass());
|
||||
Instantiator<ConfigDataLoader<?>> instantiator = new Instantiator<>(ConfigDataLoader.class,
|
||||
(availableParameters) -> {
|
||||
availableParameters.add(Log.class, logFactory::getLog);
|
||||
availableParameters.add(DeferredLogFactory.class, logFactory);
|
||||
availableParameters.add(ConfigurableBootstrapContext.class, bootstrapContext);
|
||||
availableParameters.add(BootstrapContext.class, bootstrapContext);
|
||||
availableParameters.add(BootstrapRegistry.class, bootstrapContext);
|
||||
});
|
||||
this.loaders = instantiator.instantiate(classLoader, names);
|
||||
SpringFactoriesLoader.ArgumentResolver argumentResolver = SpringFactoriesLoader.ArgumentResolver
|
||||
.of(DeferredLogFactory.class, logFactory).and(ConfigurableBootstrapContext.class, bootstrapContext)
|
||||
.and(BootstrapContext.class, bootstrapContext).and(BootstrapRegistry.class, bootstrapContext);
|
||||
this.loaders = springFactoriesLoader.load(ConfigDataLoader.class, argumentResolver);
|
||||
this.resourceTypes = getResourceTypes(this.loaders);
|
||||
}
|
||||
|
||||
private List<Class<?>> getResourceTypes(List<ConfigDataLoader<?>> loaders) {
|
||||
@SuppressWarnings("rawtypes")
|
||||
private List<Class<?>> getResourceTypes(List<ConfigDataLoader> loaders) {
|
||||
List<Class<?>> resourceTypes = new ArrayList<>(loaders.size());
|
||||
for (ConfigDataLoader<?> loader : loaders) {
|
||||
resourceTypes.add(getResourceType(loader));
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -19,8 +19,6 @@ package org.springframework.boot.context.config;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import org.springframework.boot.BootstrapContext;
|
||||
import org.springframework.boot.BootstrapRegistry;
|
||||
import org.springframework.boot.ConfigurableBootstrapContext;
|
||||
|
|
@ -37,8 +35,7 @@ import org.springframework.core.io.ResourceLoader;
|
|||
* {@code spring.factories} entries. The following constructor parameter types are
|
||||
* supported:
|
||||
* <ul>
|
||||
* <li>{@link Log} or {@link DeferredLogFactory} - if the resolver needs deferred
|
||||
* logging</li>
|
||||
* <li>{@link DeferredLogFactory} - if the resolver needs deferred logging</li>
|
||||
* <li>{@link Binder} - if the resolver needs to obtain values from the initial
|
||||
* {@link Environment}</li>
|
||||
* <li>{@link ResourceLoader} - if the resolver needs a resource loader</li>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -28,7 +28,6 @@ import org.springframework.boot.BootstrapRegistry;
|
|||
import org.springframework.boot.ConfigurableBootstrapContext;
|
||||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
import org.springframework.boot.logging.DeferredLogFactory;
|
||||
import org.springframework.boot.util.Instantiator;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
|
|
@ -50,37 +49,19 @@ class ConfigDataLocationResolvers {
|
|||
* @param bootstrapContext the bootstrap context
|
||||
* @param binder a binder providing values from the initial {@link Environment}
|
||||
* @param resourceLoader {@link ResourceLoader} to load resource locations
|
||||
* @param springFactoriesLoader to load {@link ConfigDataLocationResolver} instances
|
||||
*/
|
||||
ConfigDataLocationResolvers(DeferredLogFactory logFactory, ConfigurableBootstrapContext bootstrapContext,
|
||||
Binder binder, ResourceLoader resourceLoader) {
|
||||
this(logFactory, bootstrapContext, binder, resourceLoader, SpringFactoriesLoader
|
||||
.loadFactoryNames(ConfigDataLocationResolver.class, resourceLoader.getClassLoader()));
|
||||
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);
|
||||
this.resolvers = reorder(springFactoriesLoader.load(ConfigDataLocationResolver.class, argumentResolver));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link ConfigDataLocationResolvers} instance.
|
||||
* @param logFactory a {@link DeferredLogFactory} used to inject {@link Log} instances
|
||||
* @param bootstrapContext the bootstrap context
|
||||
* @param binder {@link Binder} providing values from the initial {@link Environment}
|
||||
* @param resourceLoader {@link ResourceLoader} to load resource locations
|
||||
* @param names the {@link ConfigDataLocationResolver} class names
|
||||
*/
|
||||
ConfigDataLocationResolvers(DeferredLogFactory logFactory, ConfigurableBootstrapContext bootstrapContext,
|
||||
Binder binder, ResourceLoader resourceLoader, List<String> names) {
|
||||
Instantiator<ConfigDataLocationResolver<?>> instantiator = new Instantiator<>(ConfigDataLocationResolver.class,
|
||||
(availableParameters) -> {
|
||||
availableParameters.add(Log.class, logFactory::getLog);
|
||||
availableParameters.add(DeferredLogFactory.class, logFactory);
|
||||
availableParameters.add(Binder.class, binder);
|
||||
availableParameters.add(ResourceLoader.class, resourceLoader);
|
||||
availableParameters.add(ConfigurableBootstrapContext.class, bootstrapContext);
|
||||
availableParameters.add(BootstrapContext.class, bootstrapContext);
|
||||
availableParameters.add(BootstrapRegistry.class, bootstrapContext);
|
||||
});
|
||||
this.resolvers = reorder(instantiator.instantiate(resourceLoader.getClassLoader(), names));
|
||||
}
|
||||
|
||||
private List<ConfigDataLocationResolver<?>> reorder(List<ConfigDataLocationResolver<?>> resolvers) {
|
||||
@SuppressWarnings("rawtypes")
|
||||
private List<ConfigDataLocationResolver<?>> reorder(List<ConfigDataLocationResolver> resolvers) {
|
||||
List<ConfigDataLocationResolver<?>> reordered = new ArrayList<>(resolvers.size());
|
||||
StandardConfigDataLocationResolver resourceResolver = null;
|
||||
for (ConfigDataLocationResolver<?> resolver : resolvers) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -35,6 +35,7 @@ import org.apache.commons.logging.Log;
|
|||
import org.springframework.boot.context.config.LocationResourceLoader.ResourceType;
|
||||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
import org.springframework.boot.env.PropertySourceLoader;
|
||||
import org.springframework.boot.logging.DeferredLogFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
|
@ -79,12 +80,13 @@ public class StandardConfigDataLocationResolver
|
|||
|
||||
/**
|
||||
* Create a new {@link StandardConfigDataLocationResolver} instance.
|
||||
* @param logger the logger to use
|
||||
* @param logFactory the factory for loggers to use
|
||||
* @param binder a binder backed by the initial {@link Environment}
|
||||
* @param resourceLoader a {@link ResourceLoader} used to load resources
|
||||
*/
|
||||
public StandardConfigDataLocationResolver(Log logger, Binder binder, ResourceLoader resourceLoader) {
|
||||
this.logger = logger;
|
||||
public StandardConfigDataLocationResolver(DeferredLogFactory logFactory, Binder binder,
|
||||
ResourceLoader resourceLoader) {
|
||||
this.logger = logFactory.getLog(StandardConfigDataLocationResolver.class);
|
||||
this.propertySourceLoaders = SpringFactoriesLoader.loadFactories(PropertySourceLoader.class,
|
||||
getClass().getClassLoader());
|
||||
this.configNames = getConfigNames(binder);
|
||||
|
|
|
|||
|
|
@ -25,12 +25,12 @@ import org.apache.commons.logging.LogFactory;
|
|||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.boot.SpringBootExceptionReporter;
|
||||
import org.springframework.boot.util.Instantiator;
|
||||
import org.springframework.boot.util.Instantiator.FailureHandler;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
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.io.support.SpringFactoriesLoader.FailureHandler;
|
||||
import org.springframework.core.log.LogMessage;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
|
@ -51,41 +51,30 @@ final class FailureAnalyzers implements SpringBootExceptionReporter {
|
|||
|
||||
private static final Log logger = LogFactory.getLog(FailureAnalyzers.class);
|
||||
|
||||
private final ClassLoader classLoader;
|
||||
private final SpringFactoriesLoader springFactoriesLoader;
|
||||
|
||||
private final List<FailureAnalyzer> analyzers;
|
||||
|
||||
FailureAnalyzers(ConfigurableApplicationContext context) {
|
||||
this(context, SpringFactoriesLoader.loadFactoryNames(FailureAnalyzer.class, getClassLoader(context)));
|
||||
public FailureAnalyzers(ConfigurableApplicationContext context) {
|
||||
this(context,
|
||||
SpringFactoriesLoader.forDefaultResourceLocation((context != null) ? context.getClassLoader() : null));
|
||||
}
|
||||
|
||||
FailureAnalyzers(ConfigurableApplicationContext context, List<String> classNames) {
|
||||
this.classLoader = getClassLoader(context);
|
||||
this.analyzers = loadFailureAnalyzers(classNames, context);
|
||||
FailureAnalyzers(ConfigurableApplicationContext context, SpringFactoriesLoader springFactoriesLoader) {
|
||||
this.springFactoriesLoader = springFactoriesLoader;
|
||||
this.analyzers = loadFailureAnalyzers(context, this.springFactoriesLoader);
|
||||
}
|
||||
|
||||
private static ClassLoader getClassLoader(ConfigurableApplicationContext context) {
|
||||
return (context != null) ? context.getClassLoader() : null;
|
||||
}
|
||||
|
||||
private List<FailureAnalyzer> loadFailureAnalyzers(List<String> classNames,
|
||||
ConfigurableApplicationContext context) {
|
||||
Instantiator<FailureAnalyzer> instantiator = new Instantiator<>(FailureAnalyzer.class,
|
||||
(availableParameters) -> {
|
||||
if (context != null) {
|
||||
availableParameters.add(BeanFactory.class, context.getBeanFactory());
|
||||
availableParameters.add(Environment.class, context.getEnvironment());
|
||||
}
|
||||
}, new LoggingInstantiationFailureHandler());
|
||||
List<FailureAnalyzer> analyzers = instantiator.instantiate(this.classLoader, classNames);
|
||||
return handleAwareAnalyzers(analyzers, context);
|
||||
}
|
||||
|
||||
private List<FailureAnalyzer> handleAwareAnalyzers(List<FailureAnalyzer> analyzers,
|
||||
ConfigurableApplicationContext context) {
|
||||
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> awareAnalyzers = analyzers.stream()
|
||||
.filter((analyzer) -> analyzer instanceof BeanFactoryAware || analyzer instanceof EnvironmentAware)
|
||||
.collect(Collectors.toList());
|
||||
.toList();
|
||||
if (!awareAnalyzers.isEmpty()) {
|
||||
String awareAnalyzerNames = StringUtils.collectionToCommaDelimitedString(awareAnalyzers.stream()
|
||||
.map((analyzer) -> analyzer.getClass().getName()).collect(Collectors.toList()));
|
||||
|
|
@ -115,7 +104,7 @@ final class FailureAnalyzers implements SpringBootExceptionReporter {
|
|||
@Override
|
||||
public boolean reportException(Throwable failure) {
|
||||
FailureAnalysis analysis = analyze(failure, this.analyzers);
|
||||
return report(analysis, this.classLoader);
|
||||
return report(analysis);
|
||||
}
|
||||
|
||||
private FailureAnalysis analyze(Throwable failure, List<FailureAnalyzer> analyzers) {
|
||||
|
|
@ -133,9 +122,8 @@ final class FailureAnalyzers implements SpringBootExceptionReporter {
|
|||
return null;
|
||||
}
|
||||
|
||||
private boolean report(FailureAnalysis analysis, ClassLoader classLoader) {
|
||||
List<FailureAnalysisReporter> reporters = SpringFactoriesLoader.loadFactories(FailureAnalysisReporter.class,
|
||||
classLoader);
|
||||
private boolean report(FailureAnalysis analysis) {
|
||||
List<FailureAnalysisReporter> reporters = this.springFactoriesLoader.load(FailureAnalysisReporter.class);
|
||||
if (analysis == null || reporters.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -145,13 +133,4 @@ final class FailureAnalyzers implements SpringBootExceptionReporter {
|
|||
return true;
|
||||
}
|
||||
|
||||
static class LoggingInstantiationFailureHandler implements FailureHandler {
|
||||
|
||||
@Override
|
||||
public void handleFailure(Class<?> type, String implementationName, Throwable failure) {
|
||||
logger.trace(LogMessage.format("Skipping %s: %s", implementationName, failure.getMessage()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -16,8 +16,6 @@
|
|||
|
||||
package org.springframework.boot.env;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import org.springframework.boot.BootstrapContext;
|
||||
import org.springframework.boot.BootstrapRegistry;
|
||||
import org.springframework.boot.ConfigurableBootstrapContext;
|
||||
|
|
@ -42,8 +40,6 @@ import org.springframework.core.env.Environment;
|
|||
* <li>{@link DeferredLogFactory} - A factory that can be used to create loggers with
|
||||
* output deferred until the application has been fully prepared (allowing the environment
|
||||
* itself to configure logging levels).</li>
|
||||
* <li>{@link Log} - A log with output deferred until the application has been fully
|
||||
* prepared (allowing the environment itself to configure logging levels).</li>
|
||||
* <li>{@link ConfigurableBootstrapContext} - A bootstrap context that can be used to
|
||||
* store objects that may be expensive to create, or need to be shared
|
||||
* ({@link BootstrapContext} or {@link BootstrapRegistry} may also be used).</li>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -56,7 +56,7 @@ public class EnvironmentPostProcessorApplicationListener implements SmartApplica
|
|||
* {@link EnvironmentPostProcessor} classes loaded via {@code spring.factories}.
|
||||
*/
|
||||
public EnvironmentPostProcessorApplicationListener() {
|
||||
this((classLoader) -> EnvironmentPostProcessorsFactory.fromSpringFactories(classLoader), new DeferredLogs());
|
||||
this((classLoader) -> EnvironmentPostProcessorsFactory.fromSpringFactories(classLoader));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -64,14 +64,21 @@ public class EnvironmentPostProcessorApplicationListener implements SmartApplica
|
|||
* processors created by the given factory.
|
||||
* @param postProcessorsFactory the post processors factory
|
||||
*/
|
||||
public EnvironmentPostProcessorApplicationListener(EnvironmentPostProcessorsFactory postProcessorsFactory) {
|
||||
this((classloader) -> postProcessorsFactory, new DeferredLogs());
|
||||
private EnvironmentPostProcessorApplicationListener(
|
||||
Function<ClassLoader, EnvironmentPostProcessorsFactory> postProcessorsFactory) {
|
||||
this.postProcessorsFactory = postProcessorsFactory;
|
||||
this.deferredLogs = new DeferredLogs();
|
||||
}
|
||||
|
||||
EnvironmentPostProcessorApplicationListener(
|
||||
Function<ClassLoader, EnvironmentPostProcessorsFactory> postProcessorsFactory, DeferredLogs deferredLogs) {
|
||||
this.postProcessorsFactory = postProcessorsFactory;
|
||||
this.deferredLogs = deferredLogs;
|
||||
/**
|
||||
* Factory method that creates an {@link EnvironmentPostProcessorApplicationListener}
|
||||
* with a specific {@link EnvironmentPostProcessorsFactory}.
|
||||
* @param postProcessorsFactory the environment post processor factory
|
||||
* @return an {@link EnvironmentPostProcessorApplicationListener} instance
|
||||
*/
|
||||
public static EnvironmentPostProcessorApplicationListener with(
|
||||
EnvironmentPostProcessorsFactory postProcessorsFactory) {
|
||||
return new EnvironmentPostProcessorApplicationListener((classloader) -> postProcessorsFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -48,8 +48,8 @@ public interface EnvironmentPostProcessorsFactory {
|
|||
* @return an {@link EnvironmentPostProcessorsFactory} instance
|
||||
*/
|
||||
static EnvironmentPostProcessorsFactory fromSpringFactories(ClassLoader classLoader) {
|
||||
return new ReflectionEnvironmentPostProcessorsFactory(classLoader,
|
||||
SpringFactoriesLoader.loadFactoryNames(EnvironmentPostProcessor.class, classLoader));
|
||||
return new SpringFactoriesEnvironmentPostProcessorsFactory(
|
||||
SpringFactoriesLoader.forDefaultResourceLocation(classLoader));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package org.springframework.boot.env;
|
|||
import org.apache.commons.logging.Log;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.logging.DeferredLogFactory;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
|
||||
|
|
@ -39,10 +40,11 @@ public class RandomValuePropertySourceEnvironmentPostProcessor implements Enviro
|
|||
|
||||
/**
|
||||
* Create a new {@link RandomValuePropertySourceEnvironmentPostProcessor} instance.
|
||||
* @param logger the logger to use
|
||||
* @param logFactory the log factory to use
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public RandomValuePropertySourceEnvironmentPostProcessor(Log logger) {
|
||||
this.logger = logger;
|
||||
public RandomValuePropertySourceEnvironmentPostProcessor(DeferredLogFactory logFactory) {
|
||||
this.logger = logFactory.getLog(RandomValuePropertySourceEnvironmentPostProcessor.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.env;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.BootstrapContext;
|
||||
import org.springframework.boot.BootstrapRegistry;
|
||||
import org.springframework.boot.ConfigurableBootstrapContext;
|
||||
import org.springframework.boot.logging.DeferredLogFactory;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
|
||||
/**
|
||||
* An {@link EnvironmentPostProcessorsFactory} that uses {@link SpringFactoriesLoader}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class SpringFactoriesEnvironmentPostProcessorsFactory implements EnvironmentPostProcessorsFactory {
|
||||
|
||||
private final SpringFactoriesLoader loader;
|
||||
|
||||
SpringFactoriesEnvironmentPostProcessorsFactory(SpringFactoriesLoader loader) {
|
||||
this.loader = loader;
|
||||
}
|
||||
|
||||
@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);
|
||||
return this.loader.load(EnvironmentPostProcessor.class, argumentResolver);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -33,7 +33,6 @@ import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
|||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.boot.util.Instantiator;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||
|
|
@ -151,10 +150,10 @@ public class DatabaseInitializationDependencyConfigurer implements ImportBeanDef
|
|||
}
|
||||
|
||||
private <T> List<T> getDetectors(ConfigurableListableBeanFactory beanFactory, Class<T> type) {
|
||||
List<String> names = SpringFactoriesLoader.loadFactoryNames(type, beanFactory.getBeanClassLoader());
|
||||
Instantiator<T> instantiator = new Instantiator<>(type,
|
||||
(availableParameters) -> availableParameters.add(Environment.class, this.environment));
|
||||
return instantiator.instantiate(beanFactory.getBeanClassLoader(), names);
|
||||
SpringFactoriesLoader.ArgumentResolver argumentResolver = SpringFactoriesLoader.ArgumentResolver
|
||||
.of(Environment.class, this.environment);
|
||||
return SpringFactoriesLoader.forDefaultResourceLocation(beanFactory.getBeanClassLoader()).load(type,
|
||||
argumentResolver);
|
||||
}
|
||||
|
||||
private static BeanDefinition getBeanDefinition(String beanName, ConfigurableListableBeanFactory beanFactory) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -16,7 +16,8 @@
|
|||
|
||||
package org.springframework.boot.cloud.cloudfoundry;
|
||||
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor;
|
||||
|
|
@ -35,7 +36,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
class CloudFoundryVcapEnvironmentPostProcessorTests {
|
||||
|
||||
private final CloudFoundryVcapEnvironmentPostProcessor initializer = new CloudFoundryVcapEnvironmentPostProcessor(
|
||||
LogFactory.getLog(getClass()));
|
||||
Supplier::get);
|
||||
|
||||
private final ConfigurableApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ import org.springframework.boot.context.properties.bind.BindException;
|
|||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
import org.springframework.boot.logging.DeferredLogFactory;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
import org.springframework.mock.env.MockPropertySource;
|
||||
|
||||
|
|
@ -86,9 +87,10 @@ class ConfigDataEnvironmentContributorsTests {
|
|||
this.environment = new MockEnvironment();
|
||||
this.binder = Binder.get(this.environment);
|
||||
ConfigDataLocationResolvers resolvers = new ConfigDataLocationResolvers(this.logFactory, this.bootstrapContext,
|
||||
this.binder, new DefaultResourceLoader(getClass().getClassLoader()));
|
||||
this.binder, new DefaultResourceLoader(getClass().getClassLoader()),
|
||||
SpringFactoriesLoader.forDefaultResourceLocation(getClass().getClassLoader()));
|
||||
ConfigDataLoaders loaders = new ConfigDataLoaders(this.logFactory, this.bootstrapContext,
|
||||
getClass().getClassLoader());
|
||||
SpringFactoriesLoader.forDefaultResourceLocation());
|
||||
this.importer = new ConfigDataImporter(this.logFactory, ConfigDataNotFoundAction.FAIL, resolvers, loaders);
|
||||
this.activationContext = new ConfigDataActivationContext(CloudPlatform.KUBERNETES, null);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -16,13 +16,14 @@
|
|||
|
||||
package org.springframework.boot.context.config;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
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;
|
||||
|
||||
import org.springframework.boot.BootstrapContext;
|
||||
import org.springframework.boot.BootstrapRegistry;
|
||||
|
|
@ -30,6 +31,7 @@ import org.springframework.boot.BootstrapRegistry.InstanceSupplier;
|
|||
import org.springframework.boot.ConfigurableBootstrapContext;
|
||||
import org.springframework.boot.DefaultBootstrapContext;
|
||||
import org.springframework.boot.logging.DeferredLogFactory;
|
||||
import org.springframework.boot.testsupport.mock.MockSpringFactoriesLoader;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.mock.env.MockPropertySource;
|
||||
|
||||
|
|
@ -51,16 +53,15 @@ class ConfigDataLoadersTests {
|
|||
|
||||
private ConfigDataLoaderContext context = mock(ConfigDataLoaderContext.class);
|
||||
|
||||
@Test
|
||||
void createWhenLoaderHasLogParameterInjectsLog() {
|
||||
new ConfigDataLoaders(this.logFactory, this.bootstrapContext, null,
|
||||
Arrays.asList(LoggingConfigDataLoader.class.getName()));
|
||||
}
|
||||
@TempDir
|
||||
private File tempDir;
|
||||
|
||||
@Test
|
||||
void createWhenLoaderHasDeferredLogFactoryParameterInjectsDeferredLogFactory() {
|
||||
ConfigDataLoaders loaders = new ConfigDataLoaders(this.logFactory, this.bootstrapContext, null,
|
||||
Arrays.asList(DeferredLogFactoryConfigDataLoader.class.getName()));
|
||||
MockSpringFactoriesLoader springFactoriesLoader = new MockSpringFactoriesLoader();
|
||||
springFactoriesLoader.add(ConfigDataLoader.class, DeferredLogFactoryConfigDataLoader.class);
|
||||
ConfigDataLoaders loaders = new ConfigDataLoaders(this.logFactory, this.bootstrapContext,
|
||||
springFactoriesLoader);
|
||||
assertThat(loaders).extracting("loaders").asList()
|
||||
.satisfies(this::containsValidDeferredLogFactoryConfigDataLoader);
|
||||
}
|
||||
|
|
@ -73,43 +74,52 @@ class ConfigDataLoadersTests {
|
|||
|
||||
@Test
|
||||
void createWhenLoaderHasBootstrapParametersInjectsBootstrapContext() {
|
||||
new ConfigDataLoaders(this.logFactory, this.bootstrapContext, null,
|
||||
Arrays.asList(BootstrappingConfigDataLoader.class.getName()));
|
||||
MockSpringFactoriesLoader springFactoriesLoader = new MockSpringFactoriesLoader();
|
||||
springFactoriesLoader.add(ConfigDataLoader.class, BootstrappingConfigDataLoader.class);
|
||||
new ConfigDataLoaders(this.logFactory, this.bootstrapContext, springFactoriesLoader);
|
||||
assertThat(this.bootstrapContext.get(String.class)).isEqualTo("boot");
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadWhenSingleLoaderSupportsLocationReturnsLoadedConfigData() throws Exception {
|
||||
MockSpringFactoriesLoader springFactoriesLoader = new MockSpringFactoriesLoader();
|
||||
springFactoriesLoader.add(ConfigDataLoader.class, TestConfigDataLoader.class);
|
||||
ConfigDataLoaders loaders = new ConfigDataLoaders(this.logFactory, this.bootstrapContext,
|
||||
springFactoriesLoader);
|
||||
TestConfigDataResource location = new TestConfigDataResource("test");
|
||||
ConfigDataLoaders loaders = new ConfigDataLoaders(this.logFactory, this.bootstrapContext, null,
|
||||
Arrays.asList(TestConfigDataLoader.class.getName()));
|
||||
ConfigData loaded = loaders.load(this.context, location);
|
||||
assertThat(getLoader(loaded)).isInstanceOf(TestConfigDataLoader.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadWhenMultipleLoadersSupportLocationThrowsException() {
|
||||
MockSpringFactoriesLoader springFactoriesLoader = new MockSpringFactoriesLoader();
|
||||
springFactoriesLoader.add(ConfigDataLoader.class, AnotherConfigDataLoader.class, TestConfigDataLoader.class);
|
||||
ConfigDataLoaders loaders = new ConfigDataLoaders(this.logFactory, this.bootstrapContext,
|
||||
springFactoriesLoader);
|
||||
TestConfigDataResource location = new TestConfigDataResource("test");
|
||||
ConfigDataLoaders loaders = new ConfigDataLoaders(this.logFactory, this.bootstrapContext, null,
|
||||
Arrays.asList(LoggingConfigDataLoader.class.getName(), TestConfigDataLoader.class.getName()));
|
||||
assertThatIllegalStateException().isThrownBy(() -> loaders.load(this.context, location))
|
||||
.withMessageContaining("Multiple loaders found for resource 'test'");
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadWhenNoLoaderSupportsLocationThrowsException() {
|
||||
MockSpringFactoriesLoader springFactoriesLoader = new MockSpringFactoriesLoader();
|
||||
springFactoriesLoader.add(ConfigDataLoader.class, NonLoadableConfigDataLoader.class);
|
||||
ConfigDataLoaders loaders = new ConfigDataLoaders(this.logFactory, this.bootstrapContext,
|
||||
springFactoriesLoader);
|
||||
TestConfigDataResource location = new TestConfigDataResource("test");
|
||||
ConfigDataLoaders loaders = new ConfigDataLoaders(this.logFactory, this.bootstrapContext, null,
|
||||
Arrays.asList(NonLoadableConfigDataLoader.class.getName()));
|
||||
assertThatIllegalStateException().isThrownBy(() -> loaders.load(this.context, location))
|
||||
.withMessage("No loader found for resource 'test'");
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadWhenGenericTypeDoesNotMatchSkipsLoader() throws Exception {
|
||||
MockSpringFactoriesLoader springFactoriesLoader = new MockSpringFactoriesLoader();
|
||||
springFactoriesLoader.add(ConfigDataLoader.class, OtherConfigDataLoader.class, SpecificConfigDataLoader.class);
|
||||
ConfigDataLoaders loaders = new ConfigDataLoaders(this.logFactory, this.bootstrapContext,
|
||||
springFactoriesLoader);
|
||||
TestConfigDataResource location = new TestConfigDataResource("test");
|
||||
ConfigDataLoaders loaders = new ConfigDataLoaders(this.logFactory, this.bootstrapContext, null,
|
||||
Arrays.asList(OtherConfigDataLoader.class.getName(), SpecificConfigDataLoader.class.getName()));
|
||||
ConfigData loaded = loaders.load(this.context, location);
|
||||
assertThat(getLoader(loaded)).isInstanceOf(SpecificConfigDataLoader.class);
|
||||
}
|
||||
|
|
@ -145,19 +155,6 @@ class ConfigDataLoadersTests {
|
|||
|
||||
}
|
||||
|
||||
static class LoggingConfigDataLoader implements ConfigDataLoader<ConfigDataResource> {
|
||||
|
||||
LoggingConfigDataLoader(Log log) {
|
||||
assertThat(log).isNotNull();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigData load(ConfigDataLoaderContext context, ConfigDataResource resource) throws IOException {
|
||||
throw new AssertionError("Unexpected call");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class DeferredLogFactoryConfigDataLoader implements ConfigDataLoader<ConfigDataResource> {
|
||||
|
||||
private final DeferredLogFactory logFactory;
|
||||
|
|
@ -205,6 +202,15 @@ class ConfigDataLoadersTests {
|
|||
|
||||
}
|
||||
|
||||
static class AnotherConfigDataLoader implements ConfigDataLoader<ConfigDataResource> {
|
||||
|
||||
@Override
|
||||
public ConfigData load(ConfigDataLoaderContext context, ConfigDataResource resource) throws IOException {
|
||||
return createConfigData(this, resource);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class NonLoadableConfigDataLoader extends TestConfigDataLoader {
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -16,16 +16,14 @@
|
|||
|
||||
package org.springframework.boot.context.config;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
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.extension.ExtendWith;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
|
|
@ -36,14 +34,13 @@ import org.springframework.boot.ConfigurableBootstrapContext;
|
|||
import org.springframework.boot.DefaultBootstrapContext;
|
||||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
import org.springframework.boot.logging.DeferredLogFactory;
|
||||
import org.springframework.boot.testsupport.mock.MockSpringFactoriesLoader;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Tests for {@link ConfigDataLocationResolvers}.
|
||||
|
|
@ -67,23 +64,27 @@ class ConfigDataLocationResolversTests {
|
|||
@Mock
|
||||
private Profiles profiles;
|
||||
|
||||
private ResourceLoader resourceLoader = new DefaultResourceLoader();
|
||||
@TempDir
|
||||
private File tempDir;
|
||||
|
||||
@Test
|
||||
void createWhenInjectingLogAndDeferredLogFactoryCreatesResolver() {
|
||||
void createWhenInjectingDeferredLogFactoryCreatesResolver() {
|
||||
MockSpringFactoriesLoader springFactoriesLoader = new MockSpringFactoriesLoader();
|
||||
springFactoriesLoader.add(ConfigDataLocationResolver.class, TestLogResolver.class);
|
||||
ConfigDataLocationResolvers resolvers = new ConfigDataLocationResolvers(this.logFactory, this.bootstrapContext,
|
||||
this.binder, this.resourceLoader, Collections.singletonList(TestLogResolver.class.getName()));
|
||||
this.binder, new DefaultResourceLoader(), springFactoriesLoader);
|
||||
assertThat(resolvers.getResolvers()).hasSize(1);
|
||||
assertThat(resolvers.getResolvers().get(0)).isExactlyInstanceOf(TestLogResolver.class);
|
||||
TestLogResolver resolver = (TestLogResolver) resolvers.getResolvers().get(0);
|
||||
assertThat(resolver.getDeferredLogFactory()).isSameAs(this.logFactory);
|
||||
assertThat(resolver.getLog()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void createWhenInjectingBinderCreatesResolver() {
|
||||
MockSpringFactoriesLoader springFactoriesLoader = new MockSpringFactoriesLoader();
|
||||
springFactoriesLoader.add(ConfigDataLocationResolver.class, TestBoundResolver.class);
|
||||
ConfigDataLocationResolvers resolvers = new ConfigDataLocationResolvers(this.logFactory, this.bootstrapContext,
|
||||
this.binder, this.resourceLoader, Collections.singletonList(TestBoundResolver.class.getName()));
|
||||
this.binder, new DefaultResourceLoader(), springFactoriesLoader);
|
||||
assertThat(resolvers.getResolvers()).hasSize(1);
|
||||
assertThat(resolvers.getResolvers().get(0)).isExactlyInstanceOf(TestBoundResolver.class);
|
||||
assertThat(((TestBoundResolver) resolvers.getResolvers().get(0)).getBinder()).isSameAs(this.binder);
|
||||
|
|
@ -91,35 +92,30 @@ class ConfigDataLocationResolversTests {
|
|||
|
||||
@Test
|
||||
void createWhenNotInjectingBinderCreatesResolver() {
|
||||
MockSpringFactoriesLoader springFactoriesLoader = new MockSpringFactoriesLoader();
|
||||
springFactoriesLoader.add(ConfigDataLocationResolver.class, TestResolver.class);
|
||||
ConfigDataLocationResolvers resolvers = new ConfigDataLocationResolvers(this.logFactory, this.bootstrapContext,
|
||||
this.binder, this.resourceLoader, Collections.singletonList(TestResolver.class.getName()));
|
||||
this.binder, new DefaultResourceLoader(), springFactoriesLoader);
|
||||
assertThat(resolvers.getResolvers()).hasSize(1);
|
||||
assertThat(resolvers.getResolvers().get(0)).isExactlyInstanceOf(TestResolver.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createWhenResolverHasBootstrapParametersInjectsBootstrapContext() {
|
||||
new ConfigDataLocationResolvers(this.logFactory, this.bootstrapContext, this.binder, this.resourceLoader,
|
||||
Collections.singletonList(TestBootstrappingResolver.class.getName()));
|
||||
MockSpringFactoriesLoader springFactoriesLoader = new MockSpringFactoriesLoader();
|
||||
springFactoriesLoader.add(ConfigDataLocationResolver.class, TestBootstrappingResolver.class);
|
||||
new ConfigDataLocationResolvers(this.logFactory, this.bootstrapContext, this.binder,
|
||||
new DefaultResourceLoader(), springFactoriesLoader);
|
||||
assertThat(this.bootstrapContext.get(String.class)).isEqualTo("boot");
|
||||
}
|
||||
|
||||
@Test
|
||||
void createWhenNameIsNotConfigDataLocationResolverThrowsException() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new ConfigDataLocationResolvers(this.logFactory, this.bootstrapContext, this.binder,
|
||||
this.resourceLoader, Collections.singletonList(InputStream.class.getName())))
|
||||
.withMessageContaining("Unable to instantiate").havingCause().withMessageContaining("not assignable");
|
||||
}
|
||||
|
||||
@Test
|
||||
void createOrdersResolvers() {
|
||||
List<String> names = new ArrayList<>();
|
||||
names.add(TestResolver.class.getName());
|
||||
names.add(LowestTestResolver.class.getName());
|
||||
names.add(HighestTestResolver.class.getName());
|
||||
MockSpringFactoriesLoader springFactoriesLoader = new MockSpringFactoriesLoader();
|
||||
springFactoriesLoader.add(ConfigDataLocationResolver.class, TestResolver.class, LowestTestResolver.class,
|
||||
HighestTestResolver.class);
|
||||
ConfigDataLocationResolvers resolvers = new ConfigDataLocationResolvers(this.logFactory, this.bootstrapContext,
|
||||
this.binder, this.resourceLoader, names);
|
||||
this.binder, new DefaultResourceLoader(), springFactoriesLoader);
|
||||
assertThat(resolvers.getResolvers().get(0)).isExactlyInstanceOf(HighestTestResolver.class);
|
||||
assertThat(resolvers.getResolvers().get(1)).isExactlyInstanceOf(TestResolver.class);
|
||||
assertThat(resolvers.getResolvers().get(2)).isExactlyInstanceOf(LowestTestResolver.class);
|
||||
|
|
@ -127,9 +123,11 @@ class ConfigDataLocationResolversTests {
|
|||
|
||||
@Test
|
||||
void resolveResolvesUsingFirstSupportedResolver() {
|
||||
MockSpringFactoriesLoader springFactoriesLoader = new MockSpringFactoriesLoader();
|
||||
springFactoriesLoader.add(ConfigDataLocationResolver.class, LowestTestResolver.class,
|
||||
HighestTestResolver.class);
|
||||
ConfigDataLocationResolvers resolvers = new ConfigDataLocationResolvers(this.logFactory, this.bootstrapContext,
|
||||
this.binder, this.resourceLoader,
|
||||
Arrays.asList(LowestTestResolver.class.getName(), HighestTestResolver.class.getName()));
|
||||
this.binder, new DefaultResourceLoader(), springFactoriesLoader);
|
||||
ConfigDataLocation location = ConfigDataLocation.of("LowestTestResolver:test");
|
||||
List<ConfigDataResolutionResult> resolved = resolvers.resolve(this.context, location, null);
|
||||
assertThat(resolved).hasSize(1);
|
||||
|
|
@ -141,9 +139,11 @@ class ConfigDataLocationResolversTests {
|
|||
|
||||
@Test
|
||||
void resolveWhenProfileMergesResolvedLocations() {
|
||||
MockSpringFactoriesLoader springFactoriesLoader = new MockSpringFactoriesLoader();
|
||||
springFactoriesLoader.add(ConfigDataLocationResolver.class, LowestTestResolver.class,
|
||||
HighestTestResolver.class);
|
||||
ConfigDataLocationResolvers resolvers = new ConfigDataLocationResolvers(this.logFactory, this.bootstrapContext,
|
||||
this.binder, this.resourceLoader,
|
||||
Arrays.asList(LowestTestResolver.class.getName(), HighestTestResolver.class.getName()));
|
||||
this.binder, new DefaultResourceLoader(), springFactoriesLoader);
|
||||
ConfigDataLocation location = ConfigDataLocation.of("LowestTestResolver:test");
|
||||
List<ConfigDataResolutionResult> resolved = resolvers.resolve(this.context, location, this.profiles);
|
||||
assertThat(resolved).hasSize(2);
|
||||
|
|
@ -159,9 +159,11 @@ class ConfigDataLocationResolversTests {
|
|||
|
||||
@Test
|
||||
void resolveWhenNoResolverThrowsException() {
|
||||
MockSpringFactoriesLoader springFactoriesLoader = new MockSpringFactoriesLoader();
|
||||
springFactoriesLoader.add(ConfigDataLocationResolver.class, LowestTestResolver.class,
|
||||
HighestTestResolver.class);
|
||||
ConfigDataLocationResolvers resolvers = new ConfigDataLocationResolvers(this.logFactory, this.bootstrapContext,
|
||||
this.binder, this.resourceLoader,
|
||||
Arrays.asList(LowestTestResolver.class.getName(), HighestTestResolver.class.getName()));
|
||||
this.binder, new DefaultResourceLoader(), springFactoriesLoader);
|
||||
ConfigDataLocation location = ConfigDataLocation.of("Missing:test");
|
||||
assertThatExceptionOfType(UnsupportedConfigDataLocationException.class)
|
||||
.isThrownBy(() -> resolvers.resolve(this.context, location, null))
|
||||
|
|
@ -170,8 +172,10 @@ class ConfigDataLocationResolversTests {
|
|||
|
||||
@Test
|
||||
void resolveWhenOptional() {
|
||||
MockSpringFactoriesLoader springFactoriesLoader = new MockSpringFactoriesLoader();
|
||||
springFactoriesLoader.add(ConfigDataLocationResolver.class, OptionalResourceTestResolver.class);
|
||||
ConfigDataLocationResolvers resolvers = new ConfigDataLocationResolvers(this.logFactory, this.bootstrapContext,
|
||||
this.binder, this.resourceLoader, Arrays.asList(OptionalResourceTestResolver.class.getName()));
|
||||
this.binder, new DefaultResourceLoader(), springFactoriesLoader);
|
||||
ConfigDataLocation location = ConfigDataLocation.of("OptionalResourceTestResolver:test");
|
||||
List<ConfigDataResolutionResult> resolved = resolvers.resolve(this.context, location, null);
|
||||
assertThat(resolved.get(0).getResource().isOptional()).isTrue();
|
||||
|
|
@ -185,7 +189,7 @@ class ConfigDataLocationResolversTests {
|
|||
this(false);
|
||||
}
|
||||
|
||||
TestResolver(boolean optionalResource) {
|
||||
private TestResolver(boolean optionalResource) {
|
||||
this.optionalResource = optionalResource;
|
||||
}
|
||||
|
||||
|
|
@ -214,21 +218,14 @@ class ConfigDataLocationResolversTests {
|
|||
|
||||
private final DeferredLogFactory deferredLogFactory;
|
||||
|
||||
private final Log log;
|
||||
|
||||
TestLogResolver(DeferredLogFactory deferredLogFactory, Log log) {
|
||||
TestLogResolver(DeferredLogFactory deferredLogFactory) {
|
||||
this.deferredLogFactory = deferredLogFactory;
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
DeferredLogFactory getDeferredLogFactory() {
|
||||
return this.deferredLogFactory;
|
||||
}
|
||||
|
||||
Log getLog() {
|
||||
return this.log;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class TestBoundResolver extends TestResolver {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -25,7 +25,7 @@ import org.junit.jupiter.api.Test;
|
|||
|
||||
import org.springframework.boot.context.properties.bind.Binder;
|
||||
import org.springframework.boot.env.PropertiesPropertySourceLoader;
|
||||
import org.springframework.boot.logging.DeferredLog;
|
||||
import org.springframework.boot.logging.DeferredLogs;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
|
|
@ -60,7 +60,7 @@ class StandardConfigDataLocationResolverTests {
|
|||
void setup() {
|
||||
this.environment = new MockEnvironment();
|
||||
this.environmentBinder = Binder.get(this.environment);
|
||||
this.resolver = new StandardConfigDataLocationResolver(new DeferredLog(), this.environmentBinder,
|
||||
this.resolver = new StandardConfigDataLocationResolver(new DeferredLogs(), this.environmentBinder,
|
||||
this.resourceLoader);
|
||||
}
|
||||
|
||||
|
|
@ -115,8 +115,8 @@ class StandardConfigDataLocationResolverTests {
|
|||
void createWhenConfigNameHasWildcardThrowsException() {
|
||||
this.environment.setProperty("spring.config.name", "*/application");
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(
|
||||
() -> new StandardConfigDataLocationResolver(null, this.environmentBinder, this.resourceLoader))
|
||||
.isThrownBy(() -> new StandardConfigDataLocationResolver(new DeferredLogs(), this.environmentBinder,
|
||||
this.resourceLoader))
|
||||
.withMessageStartingWith("Config name '").withMessageEndingWith("' cannot contain '*'");
|
||||
}
|
||||
|
||||
|
|
@ -131,7 +131,8 @@ class StandardConfigDataLocationResolverTests {
|
|||
void resolveWhenLocationIsWildcardDirectoriesRestrictsToOneLevelDeep() {
|
||||
ConfigDataLocation location = ConfigDataLocation.of("file:src/test/resources/config/*/");
|
||||
this.environment.setProperty("spring.config.name", "testproperties");
|
||||
this.resolver = new StandardConfigDataLocationResolver(null, this.environmentBinder, this.resourceLoader);
|
||||
this.resolver = new StandardConfigDataLocationResolver(new DeferredLogs(), this.environmentBinder,
|
||||
this.resourceLoader);
|
||||
List<StandardConfigDataResource> locations = this.resolver.resolve(this.context, location);
|
||||
assertThat(locations.size()).isEqualTo(3);
|
||||
assertThat(locations).extracting(Object::toString)
|
||||
|
|
@ -144,7 +145,8 @@ class StandardConfigDataLocationResolverTests {
|
|||
void resolveWhenLocationIsWildcardDirectoriesSortsAlphabeticallyBasedOnAbsolutePath() {
|
||||
ConfigDataLocation location = ConfigDataLocation.of("file:src/test/resources/config/*/");
|
||||
this.environment.setProperty("spring.config.name", "testproperties");
|
||||
this.resolver = new StandardConfigDataLocationResolver(null, this.environmentBinder, this.resourceLoader);
|
||||
this.resolver = new StandardConfigDataLocationResolver(new DeferredLogs(), this.environmentBinder,
|
||||
this.resourceLoader);
|
||||
List<StandardConfigDataResource> locations = this.resolver.resolve(this.context, location);
|
||||
assertThat(locations).extracting(Object::toString).containsExactly(
|
||||
filePath("src", "test", "resources", "config", "0-empty", "testproperties.properties"),
|
||||
|
|
@ -175,7 +177,7 @@ class StandardConfigDataLocationResolverTests {
|
|||
void resolveWhenLocationIsRelativeAndFileResolves() {
|
||||
this.environment.setProperty("spring.config.name", "other");
|
||||
ConfigDataLocation location = ConfigDataLocation.of("other.properties");
|
||||
this.resolver = new StandardConfigDataLocationResolver(new DeferredLog(), this.environmentBinder,
|
||||
this.resolver = new StandardConfigDataLocationResolver(new DeferredLogs(), this.environmentBinder,
|
||||
this.resourceLoader);
|
||||
StandardConfigDataReference parentReference = new StandardConfigDataReference(
|
||||
ConfigDataLocation.of("classpath:configdata/properties/application.properties"), null,
|
||||
|
|
@ -194,7 +196,7 @@ class StandardConfigDataLocationResolverTests {
|
|||
void resolveWhenLocationIsRelativeAndDirectoryResolves() {
|
||||
this.environment.setProperty("spring.config.name", "testproperties");
|
||||
ConfigDataLocation location = ConfigDataLocation.of("nested/3-third/");
|
||||
this.resolver = new StandardConfigDataLocationResolver(new DeferredLog(), this.environmentBinder,
|
||||
this.resolver = new StandardConfigDataLocationResolver(new DeferredLogs(), this.environmentBinder,
|
||||
this.resourceLoader);
|
||||
StandardConfigDataReference parentReference = new StandardConfigDataReference(
|
||||
ConfigDataLocation.of("optional:classpath:configdata/"), null, "classpath:config/specific", null,
|
||||
|
|
|
|||
|
|
@ -16,14 +16,13 @@
|
|||
|
||||
package org.springframework.boot.diagnostics;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.boot.testsupport.mock.MockSpringFactoriesLoader;
|
||||
import org.springframework.boot.testsupport.system.CapturedOutput;
|
||||
import org.springframework.boot.testsupport.system.OutputCaptureExtension;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
|
|
@ -58,15 +57,14 @@ class FailureAnalyzersTests {
|
|||
@Test
|
||||
void analyzersAreLoadedAndCalled() {
|
||||
RuntimeException failure = new RuntimeException();
|
||||
analyzeAndReport(failure, BasicFailureAnalyzer.class.getName(), BasicFailureAnalyzer.class.getName());
|
||||
analyzeAndReport(failure, BasicFailureAnalyzer.class, StandardAwareFailureAnalyzer.class);
|
||||
then(failureAnalyzer).should(times(2)).analyze(failure);
|
||||
}
|
||||
|
||||
@Test
|
||||
void analyzerIsConstructedWithBeanFactory(CapturedOutput output) {
|
||||
RuntimeException failure = new RuntimeException();
|
||||
analyzeAndReport(failure, BasicFailureAnalyzer.class.getName(),
|
||||
BeanFactoryConstructorFailureAnalyzer.class.getName());
|
||||
analyzeAndReport(failure, BasicFailureAnalyzer.class, BeanFactoryConstructorFailureAnalyzer.class);
|
||||
then(failureAnalyzer).should(times(2)).analyze(failure);
|
||||
assertThat(output).doesNotContain("implement BeanFactoryAware or EnvironmentAware");
|
||||
}
|
||||
|
|
@ -74,8 +72,7 @@ class FailureAnalyzersTests {
|
|||
@Test
|
||||
void analyzerIsConstructedWithEnvironment(CapturedOutput output) {
|
||||
RuntimeException failure = new RuntimeException();
|
||||
analyzeAndReport(failure, BasicFailureAnalyzer.class.getName(),
|
||||
EnvironmentConstructorFailureAnalyzer.class.getName());
|
||||
analyzeAndReport(failure, BasicFailureAnalyzer.class, EnvironmentConstructorFailureAnalyzer.class);
|
||||
then(failureAnalyzer).should(times(2)).analyze(failure);
|
||||
assertThat(output).doesNotContain("implement BeanFactoryAware or EnvironmentAware");
|
||||
}
|
||||
|
|
@ -83,7 +80,7 @@ class FailureAnalyzersTests {
|
|||
@Test
|
||||
void beanFactoryIsInjectedIntoBeanFactoryAwareFailureAnalyzers(CapturedOutput output) {
|
||||
RuntimeException failure = new RuntimeException();
|
||||
analyzeAndReport(failure, BasicFailureAnalyzer.class.getName(), StandardAwareFailureAnalyzer.class.getName());
|
||||
analyzeAndReport(failure, BasicFailureAnalyzer.class, StandardAwareFailureAnalyzer.class);
|
||||
then(failureAnalyzer).should().setBeanFactory(same(this.context.getBeanFactory()));
|
||||
assertThat(output).contains("FailureAnalyzers [" + StandardAwareFailureAnalyzer.class.getName()
|
||||
+ "] implement BeanFactoryAware or EnvironmentAware.");
|
||||
|
|
@ -92,41 +89,37 @@ class FailureAnalyzersTests {
|
|||
@Test
|
||||
void environmentIsInjectedIntoEnvironmentAwareFailureAnalyzers() {
|
||||
RuntimeException failure = new RuntimeException();
|
||||
analyzeAndReport(failure, BasicFailureAnalyzer.class.getName(), StandardAwareFailureAnalyzer.class.getName());
|
||||
analyzeAndReport(failure, BasicFailureAnalyzer.class, StandardAwareFailureAnalyzer.class);
|
||||
then(failureAnalyzer).should().setEnvironment(same(this.context.getEnvironment()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void analyzerThatFailsDuringInitializationDoesNotPreventOtherAnalyzersFromBeingCalled() {
|
||||
RuntimeException failure = new RuntimeException();
|
||||
analyzeAndReport(failure, BrokenInitializationFailureAnalyzer.class.getName(),
|
||||
BasicFailureAnalyzer.class.getName());
|
||||
analyzeAndReport(failure, BrokenInitializationFailureAnalyzer.class, BasicFailureAnalyzer.class);
|
||||
then(failureAnalyzer).should().analyze(failure);
|
||||
}
|
||||
|
||||
@Test
|
||||
void analyzerThatFailsDuringAnalysisDoesNotPreventOtherAnalyzersFromBeingCalled() {
|
||||
RuntimeException failure = new RuntimeException();
|
||||
analyzeAndReport(failure, BrokenAnalysisFailureAnalyzer.class.getName(), BasicFailureAnalyzer.class.getName());
|
||||
analyzeAndReport(failure, BrokenAnalysisFailureAnalyzer.class, BasicFailureAnalyzer.class);
|
||||
then(failureAnalyzer).should().analyze(failure);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createWithNullContextSkipsAwareAnalyzers() {
|
||||
RuntimeException failure = new RuntimeException();
|
||||
analyzeAndReport(failure, (AnnotationConfigApplicationContext) null, BasicFailureAnalyzer.class.getName(),
|
||||
BeanFactoryConstructorFailureAnalyzer.class.getName(),
|
||||
EnvironmentConstructorFailureAnalyzer.class.getName(), StandardAwareFailureAnalyzer.class.getName());
|
||||
then(failureAnalyzer).should().analyze(failure);
|
||||
}
|
||||
|
||||
private void analyzeAndReport(Throwable failure, String... factoryNames) {
|
||||
analyzeAndReport(failure, this.context, factoryNames);
|
||||
@SafeVarargs
|
||||
private void analyzeAndReport(Throwable failure, Class<? extends FailureAnalyzer>... failureAnalyzerClasses) {
|
||||
analyzeAndReport(failure, this.context, failureAnalyzerClasses);
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
private void analyzeAndReport(Throwable failure, AnnotationConfigApplicationContext context,
|
||||
String... factoryNames) {
|
||||
new FailureAnalyzers(context, Arrays.asList(factoryNames)).reportException(failure);
|
||||
Class<? extends FailureAnalyzer>... failureAnalyzerClasses) {
|
||||
MockSpringFactoriesLoader loader = new MockSpringFactoriesLoader();
|
||||
for (Class<? extends FailureAnalyzer> failureAnalyzerClass : failureAnalyzerClasses) {
|
||||
loader.add(FailureAnalyzer.class, failureAnalyzerClass);
|
||||
}
|
||||
new FailureAnalyzers(context, loader).reportException(failure);
|
||||
}
|
||||
|
||||
static class BasicFailureAnalyzer implements FailureAnalyzer {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@
|
|||
package org.springframework.boot.env;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.BootstrapRegistry;
|
||||
|
|
@ -32,6 +34,7 @@ import org.springframework.boot.logging.DeferredLogs;
|
|||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.then;
|
||||
|
|
@ -49,9 +52,15 @@ class EnvironmentPostProcessorApplicationListenerTests {
|
|||
|
||||
private DefaultBootstrapContext bootstrapContext = spy(new DefaultBootstrapContext());
|
||||
|
||||
private EnvironmentPostProcessorApplicationListener listener = new EnvironmentPostProcessorApplicationListener(
|
||||
(classLoader) -> EnvironmentPostProcessorsFactory.of(TestEnvironmentPostProcessor.class),
|
||||
this.deferredLogs);
|
||||
private EnvironmentPostProcessorApplicationListener listener = new EnvironmentPostProcessorApplicationListener();
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
ReflectionTestUtils.setField(this.listener, "deferredLogs", this.deferredLogs);
|
||||
ReflectionTestUtils.setField(this.listener, "postProcessorsFactory",
|
||||
(Function<ClassLoader, EnvironmentPostProcessorsFactory>) (
|
||||
classLoader) -> EnvironmentPostProcessorsFactory.of(TestEnvironmentPostProcessor.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void createUsesSpringFactories() {
|
||||
|
|
@ -61,8 +70,8 @@ class EnvironmentPostProcessorApplicationListenerTests {
|
|||
|
||||
@Test
|
||||
void createWhenHasFactoryUsesFactory() {
|
||||
EnvironmentPostProcessorApplicationListener listener = new EnvironmentPostProcessorApplicationListener(
|
||||
EnvironmentPostProcessorsFactory.of(TestEnvironmentPostProcessor.class));
|
||||
EnvironmentPostProcessorApplicationListener listener = EnvironmentPostProcessorApplicationListener
|
||||
.with(EnvironmentPostProcessorsFactory.of(TestEnvironmentPostProcessor.class));
|
||||
List<EnvironmentPostProcessor> postProcessors = listener.getEnvironmentPostProcessors(null,
|
||||
this.bootstrapContext);
|
||||
assertThat(postProcessors).hasSize(1);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
* Copyright 2012-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -16,7 +16,8 @@
|
|||
|
||||
package org.springframework.boot.env;
|
||||
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
|
|
@ -34,7 +35,7 @@ import static org.mockito.Mockito.mock;
|
|||
class RandomValuePropertySourceEnvironmentPostProcessorTests {
|
||||
|
||||
private RandomValuePropertySourceEnvironmentPostProcessor postProcessor = new RandomValuePropertySourceEnvironmentPostProcessor(
|
||||
LogFactory.getLog(getClass()));
|
||||
Supplier::get);
|
||||
|
||||
@Test
|
||||
void getOrderIsBeforeConfigData() {
|
||||
|
|
|
|||
|
|
@ -59,4 +59,5 @@
|
|||
<suppress files="DeprecatedReactiveElasticsearchRestClientProperties\.java" checks="SpringMethodVisibility" />
|
||||
<suppress files="DevToolsR2dbcAutoConfigurationTests" checks="HideUtilityClassConstructor" />
|
||||
<suppress files="AbstractLaunchScriptIntegrationTests" checks="IllegalImport" />
|
||||
<suppress files="FailureAnalyzers\.java" checks="RedundantModifier" />
|
||||
</suppressions>
|
||||
|
|
|
|||
Loading…
Reference in New Issue