Add BootstrapRegistry for long lived instances
Add a simple `BootstrapRegistry` that can be used to store and share object instances across `EnvironmentPostProcessors`. The registry can be injected into the constructor of any `EnvironmentPostProcessor`. Registrations can also perform additional actions when the `ApplicationContext` has been prepared. For example, they could register the the bootstrap instances as beans so that they become available to the application. See gh-22956
This commit is contained in:
parent
167e31d564
commit
2260657781
|
|
@ -74,7 +74,7 @@ public final class RemoteSpringApplication {
|
||||||
List<ApplicationListener<?>> listeners = new ArrayList<>();
|
List<ApplicationListener<?>> listeners = new ArrayList<>();
|
||||||
listeners.add(new AnsiOutputApplicationListener());
|
listeners.add(new AnsiOutputApplicationListener());
|
||||||
listeners.add(new EnvironmentPostProcessorApplicationListener(
|
listeners.add(new EnvironmentPostProcessorApplicationListener(
|
||||||
EnvironmentPostProcessorsFactory.singleton(ConfigDataEnvironmentPostProcessor::new)));
|
EnvironmentPostProcessorsFactory.of(ConfigDataEnvironmentPostProcessor.class)));
|
||||||
listeners.add(new ClasspathLoggingApplicationListener());
|
listeners.add(new ClasspathLoggingApplicationListener());
|
||||||
listeners.add(new LoggingApplicationListener());
|
listeners.add(new LoggingApplicationListener());
|
||||||
listeners.add(new RemoteUrlPropertyExtractor());
|
listeners.add(new RemoteUrlPropertyExtractor());
|
||||||
|
|
|
||||||
123
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/env/BootstrapRegistry.java
vendored
Normal file
123
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/env/BootstrapRegistry.java
vendored
Normal file
|
|
@ -0,0 +1,123 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2020 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.function.BiConsumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.event.ApplicationPreparedEvent;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple object registry that is available during {@link Environment} post-processing
|
||||||
|
* up to the point that the {@link ApplicationContext} is prepared. The registry can be
|
||||||
|
* used to store objects that may be expensive to create, or need to be shared by
|
||||||
|
* different {@link EnvironmentPostProcessor EnvironmentPostProcessors}.
|
||||||
|
* <p>
|
||||||
|
* The registry uses the object type as a key, meaning that only a single instance of a
|
||||||
|
* given class can be stored.
|
||||||
|
* <p>
|
||||||
|
* Registered instances may optionally use
|
||||||
|
* {@link Registration#onApplicationContextPrepared(BiConsumer)
|
||||||
|
* onApplicationContextPrepared(...)} to perform an action when the
|
||||||
|
* {@link ApplicationContext} is {@link ApplicationPreparedEvent prepared}. For example,
|
||||||
|
* an instance may choose to register itself as a regular Spring bean so that it is
|
||||||
|
* available for the application to use.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @since 2.4.0
|
||||||
|
* @see EnvironmentPostProcessor
|
||||||
|
*/
|
||||||
|
public interface BootstrapRegistry {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an instance from the registry, creating one if it does not already exist.
|
||||||
|
* @param <T> the instance type
|
||||||
|
* @param type the instance type
|
||||||
|
* @param instanceSupplier a supplier used to create the instance if it doesn't
|
||||||
|
* already exist
|
||||||
|
* @return the registered instance
|
||||||
|
*/
|
||||||
|
<T> T get(Class<T> type, Supplier<T> instanceSupplier);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an instance from the registry, creating one if it does not already exist.
|
||||||
|
* @param <T> the instance type
|
||||||
|
* @param type the instance type
|
||||||
|
* @param instanceSupplier a supplier used to create the instance if it doesn't
|
||||||
|
* already exist
|
||||||
|
* @param onApplicationContextPreparedAction the action that should be called when the
|
||||||
|
* application context is prepared. This action is ignored if the registration already
|
||||||
|
* exists.
|
||||||
|
* @return the registered instance
|
||||||
|
*/
|
||||||
|
<T> T get(Class<T> type, Supplier<T> instanceSupplier,
|
||||||
|
BiConsumer<ConfigurableApplicationContext, T> onApplicationContextPreparedAction);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register an instance with the registry and return a {@link Registration} that can
|
||||||
|
* be used to provide further configuration. This method will replace any existing
|
||||||
|
* registration.
|
||||||
|
* @param <T> the instance type
|
||||||
|
* @param type the instance type
|
||||||
|
* @param instanceSupplier a supplier used to create the instance if it doesn't
|
||||||
|
* already exist
|
||||||
|
* @return an instance registration
|
||||||
|
*/
|
||||||
|
<T> Registration<T> register(Class<T> type, Supplier<T> instanceSupplier);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return if a registration exists for the given type.
|
||||||
|
* @param <T> the instance type
|
||||||
|
* @param type the instance type
|
||||||
|
* @return {@code true} if the type has already been registered
|
||||||
|
*/
|
||||||
|
<T> boolean isRegistered(Class<T> type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return any existing {@link Registration} for the given type.
|
||||||
|
* @param <T> the instance type
|
||||||
|
* @param type the instance type
|
||||||
|
* @return the existing registration or {@code null}
|
||||||
|
*/
|
||||||
|
<T> Registration<T> getRegistration(Class<T> type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A single registration contained in the registry.
|
||||||
|
*
|
||||||
|
* @param <T> the instance type
|
||||||
|
*/
|
||||||
|
interface Registration<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get or crearte the registered object instance.
|
||||||
|
* @return the object instance
|
||||||
|
*/
|
||||||
|
T get();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an action that should run when the {@link ApplicationContext} has been
|
||||||
|
* prepared.
|
||||||
|
* @param action the action to run
|
||||||
|
*/
|
||||||
|
void onApplicationContextPrepared(BiConsumer<ConfigurableApplicationContext, T> action);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,127 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2020 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.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default implementation of {@link BootstrapRegistry}.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @since 2.4.0
|
||||||
|
*/
|
||||||
|
public class DefaultBootstrapRegisty implements BootstrapRegistry {
|
||||||
|
|
||||||
|
private final Map<Class<?>, DefaultRegistration<?>> registrations = new HashMap<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T get(Class<T> type, Supplier<T> instanceSupplier) {
|
||||||
|
return get(type, instanceSupplier, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T get(Class<T> type, Supplier<T> instanceSupplier,
|
||||||
|
BiConsumer<ConfigurableApplicationContext, T> onApplicationContextPreparedAction) {
|
||||||
|
Registration<T> registration = getRegistration(type);
|
||||||
|
if (registration != null) {
|
||||||
|
return registration.get();
|
||||||
|
}
|
||||||
|
registration = register(type, instanceSupplier);
|
||||||
|
registration.onApplicationContextPrepared(onApplicationContextPreparedAction);
|
||||||
|
return registration.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> Registration<T> register(Class<T> type, Supplier<T> instanceSupplier) {
|
||||||
|
DefaultRegistration<T> registration = new DefaultRegistration<>(instanceSupplier);
|
||||||
|
this.registrations.put(type, registration);
|
||||||
|
return registration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> boolean isRegistered(Class<T> type) {
|
||||||
|
return getRegistration(type) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> Registration<T> getRegistration(Class<T> type) {
|
||||||
|
return (Registration<T>) this.registrations.get(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to be called when the {@link ApplicationContext} is prepared.
|
||||||
|
* @param applicationContext the prepared context
|
||||||
|
*/
|
||||||
|
public void applicationContextPrepared(ConfigurableApplicationContext applicationContext) {
|
||||||
|
this.registrations.values()
|
||||||
|
.forEach((registration) -> registration.applicationContextPrepared(applicationContext));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default implementation of {@link Registration}.
|
||||||
|
*/
|
||||||
|
private static class DefaultRegistration<T> implements Registration<T> {
|
||||||
|
|
||||||
|
private Supplier<T> instanceSupplier;
|
||||||
|
|
||||||
|
private volatile T instance;
|
||||||
|
|
||||||
|
private List<BiConsumer<ConfigurableApplicationContext, T>> applicationContextPreparedActions = new ArrayList<>();
|
||||||
|
|
||||||
|
DefaultRegistration(Supplier<T> instanceSupplier) {
|
||||||
|
this.instanceSupplier = instanceSupplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T get() {
|
||||||
|
T instance = this.instance;
|
||||||
|
if (instance == null) {
|
||||||
|
synchronized (this.instanceSupplier) {
|
||||||
|
instance = this.instanceSupplier.get();
|
||||||
|
this.instance = instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onApplicationContextPrepared(BiConsumer<ConfigurableApplicationContext, T> action) {
|
||||||
|
if (action != null) {
|
||||||
|
this.applicationContextPreparedActions.add(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method called when the {@link ApplicationContext} is prepared.
|
||||||
|
* @param applicationContext the prepared context
|
||||||
|
*/
|
||||||
|
void applicationContextPrepared(ConfigurableApplicationContext applicationContext) {
|
||||||
|
this.applicationContextPreparedActions.forEach((consumer) -> consumer.accept(applicationContext, get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -34,9 +34,16 @@ import org.springframework.core.env.Environment;
|
||||||
* if they wish to be invoked in specific order.
|
* if they wish to be invoked in specific order.
|
||||||
* <p>
|
* <p>
|
||||||
* Since Spring Boot 2.4, {@code EnvironmentPostProcessor} implementations may optionally
|
* Since Spring Boot 2.4, {@code EnvironmentPostProcessor} implementations may optionally
|
||||||
* take a single {@link Log} or {@link DeferredLogFactory} instance as a constructor
|
* take the following constructor parameters:
|
||||||
* argument. The injected {@link Log} instance will defer output until the application has
|
* <ul>
|
||||||
* been full prepared to allow the environment itself to configure logging levels.
|
* <li>{@link DeferredLogFactory} - A factory that can be used to create loggers with
|
||||||
|
* output deferred until the application has been full prepared (allowing the environment
|
||||||
|
* itself to configure logging levels).</li>
|
||||||
|
* <li>{@link Log} - A log with output deferred until the application has been full
|
||||||
|
* prepared (allowing the environment itself to configure logging levels).</li>
|
||||||
|
* <li>{@link BootstrapRegistry} - A bootstrap registry that can be used to store objects
|
||||||
|
* that may be expensive to create, or need to be shared.</li>
|
||||||
|
* </ul>
|
||||||
*
|
*
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,8 @@ public class EnvironmentPostProcessorApplicationListener implements SmartApplica
|
||||||
|
|
||||||
private final DeferredLogs deferredLogs;
|
private final DeferredLogs deferredLogs;
|
||||||
|
|
||||||
|
private final DefaultBootstrapRegisty bootstrapRegistry;
|
||||||
|
|
||||||
private int order = DEFAULT_ORDER;
|
private int order = DEFAULT_ORDER;
|
||||||
|
|
||||||
private final EnvironmentPostProcessorsFactory postProcessorsFactory;
|
private final EnvironmentPostProcessorsFactory postProcessorsFactory;
|
||||||
|
|
@ -63,13 +65,14 @@ public class EnvironmentPostProcessorApplicationListener implements SmartApplica
|
||||||
* @param postProcessorsFactory the post processors factory
|
* @param postProcessorsFactory the post processors factory
|
||||||
*/
|
*/
|
||||||
public EnvironmentPostProcessorApplicationListener(EnvironmentPostProcessorsFactory postProcessorsFactory) {
|
public EnvironmentPostProcessorApplicationListener(EnvironmentPostProcessorsFactory postProcessorsFactory) {
|
||||||
this(postProcessorsFactory, new DeferredLogs());
|
this(postProcessorsFactory, new DeferredLogs(), new DefaultBootstrapRegisty());
|
||||||
}
|
}
|
||||||
|
|
||||||
EnvironmentPostProcessorApplicationListener(EnvironmentPostProcessorsFactory postProcessorsFactory,
|
EnvironmentPostProcessorApplicationListener(EnvironmentPostProcessorsFactory postProcessorsFactory,
|
||||||
DeferredLogs deferredLogs) {
|
DeferredLogs deferredLogs, DefaultBootstrapRegisty bootstrapRegistry) {
|
||||||
this.postProcessorsFactory = postProcessorsFactory;
|
this.postProcessorsFactory = postProcessorsFactory;
|
||||||
this.deferredLogs = deferredLogs;
|
this.deferredLogs = deferredLogs;
|
||||||
|
this.bootstrapRegistry = bootstrapRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -84,8 +87,11 @@ public class EnvironmentPostProcessorApplicationListener implements SmartApplica
|
||||||
if (event instanceof ApplicationEnvironmentPreparedEvent) {
|
if (event instanceof ApplicationEnvironmentPreparedEvent) {
|
||||||
onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);
|
onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);
|
||||||
}
|
}
|
||||||
if (event instanceof ApplicationPreparedEvent || event instanceof ApplicationFailedEvent) {
|
if (event instanceof ApplicationPreparedEvent) {
|
||||||
onFinish();
|
onApplicationPreparedEvent((ApplicationPreparedEvent) event);
|
||||||
|
}
|
||||||
|
if (event instanceof ApplicationFailedEvent) {
|
||||||
|
onApplicationFailedEvent((ApplicationFailedEvent) event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -97,14 +103,19 @@ public class EnvironmentPostProcessorApplicationListener implements SmartApplica
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<EnvironmentPostProcessor> getEnvironmentPostProcessors() {
|
private void onApplicationPreparedEvent(ApplicationPreparedEvent event) {
|
||||||
return this.postProcessorsFactory.getEnvironmentPostProcessors(this.deferredLogs);
|
this.deferredLogs.switchOverAll();
|
||||||
|
this.bootstrapRegistry.applicationContextPrepared(event.getApplicationContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onFinish() {
|
private void onApplicationFailedEvent(ApplicationFailedEvent event) {
|
||||||
this.deferredLogs.switchOverAll();
|
this.deferredLogs.switchOverAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<EnvironmentPostProcessor> getEnvironmentPostProcessors() {
|
||||||
|
return this.postProcessorsFactory.getEnvironmentPostProcessors(this.deferredLogs, this.bootstrapRegistry);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getOrder() {
|
public int getOrder() {
|
||||||
return this.order;
|
return this.order;
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,7 @@
|
||||||
|
|
||||||
package org.springframework.boot.env;
|
package org.springframework.boot.env;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import org.springframework.boot.logging.DeferredLogFactory;
|
import org.springframework.boot.logging.DeferredLogFactory;
|
||||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||||
|
|
@ -36,9 +34,11 @@ public interface EnvironmentPostProcessorsFactory {
|
||||||
/**
|
/**
|
||||||
* Create all requested {@link EnvironmentPostProcessor} instances.
|
* Create all requested {@link EnvironmentPostProcessor} instances.
|
||||||
* @param logFactory a deferred log factory
|
* @param logFactory a deferred log factory
|
||||||
|
* @param bootstrapRegistry a bootstrap registry
|
||||||
* @return the post processor instances
|
* @return the post processor instances
|
||||||
*/
|
*/
|
||||||
List<EnvironmentPostProcessor> getEnvironmentPostProcessors(DeferredLogFactory logFactory);
|
List<EnvironmentPostProcessor> getEnvironmentPostProcessors(DeferredLogFactory logFactory,
|
||||||
|
BootstrapRegistry bootstrapRegistry);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a {@link EnvironmentPostProcessorsFactory} backed by
|
* Return a {@link EnvironmentPostProcessorsFactory} backed by
|
||||||
|
|
@ -71,14 +71,4 @@ public interface EnvironmentPostProcessorsFactory {
|
||||||
return new ReflectionEnvironmentPostProcessorsFactory(classNames);
|
return new ReflectionEnvironmentPostProcessorsFactory(classNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a {@link EnvironmentPostProcessorsFactory} containing only a single post
|
|
||||||
* processor.
|
|
||||||
* @param factory the factory used to create the post processor
|
|
||||||
* @return an {@link EnvironmentPostProcessorsFactory} instance
|
|
||||||
*/
|
|
||||||
static EnvironmentPostProcessorsFactory singleton(Function<DeferredLogFactory, EnvironmentPostProcessor> factory) {
|
|
||||||
return (logFactory) -> Collections.singletonList(factory.apply(logFactory));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,18 +16,13 @@
|
||||||
|
|
||||||
package org.springframework.boot.env;
|
package org.springframework.boot.env;
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
|
|
||||||
import org.springframework.boot.logging.DeferredLogFactory;
|
import org.springframework.boot.logging.DeferredLogFactory;
|
||||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
import org.springframework.boot.util.Instantiator;
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.util.ClassUtils;
|
|
||||||
import org.springframework.util.ReflectionUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link EnvironmentPostProcessorsFactory} implementation that uses reflection to create
|
* {@link EnvironmentPostProcessorsFactory} implementation that uses reflection to create
|
||||||
|
|
@ -52,43 +47,15 @@ class ReflectionEnvironmentPostProcessorsFactory implements EnvironmentPostProce
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<EnvironmentPostProcessor> getEnvironmentPostProcessors(DeferredLogFactory logFactory) {
|
public List<EnvironmentPostProcessor> getEnvironmentPostProcessors(DeferredLogFactory logFactory,
|
||||||
List<EnvironmentPostProcessor> postProcessors = new ArrayList<>(this.classNames.size());
|
BootstrapRegistry bootstrapRegistry) {
|
||||||
for (String className : this.classNames) {
|
Instantiator<EnvironmentPostProcessor> instantiator = new Instantiator<>(EnvironmentPostProcessor.class,
|
||||||
try {
|
(parameters) -> {
|
||||||
postProcessors.add(getEnvironmentPostProcessor(className, logFactory));
|
parameters.add(DeferredLogFactory.class, logFactory);
|
||||||
}
|
parameters.add(Log.class, logFactory::getLog);
|
||||||
catch (Throwable ex) {
|
parameters.add(BootstrapRegistry.class, bootstrapRegistry);
|
||||||
throw new IllegalArgumentException("Unable to instantiate factory class [" + className
|
});
|
||||||
+ "] for factory type [" + EnvironmentPostProcessor.class.getName() + "]", ex);
|
return instantiator.instantiate(this.classNames);
|
||||||
}
|
|
||||||
}
|
|
||||||
AnnotationAwareOrderComparator.sort(postProcessors);
|
|
||||||
return postProcessors;
|
|
||||||
}
|
|
||||||
|
|
||||||
private EnvironmentPostProcessor getEnvironmentPostProcessor(String className, DeferredLogFactory logFactory)
|
|
||||||
throws Exception {
|
|
||||||
Class<?> type = ClassUtils.forName(className, getClass().getClassLoader());
|
|
||||||
Assert.isAssignable(EnvironmentPostProcessor.class, type);
|
|
||||||
Constructor<?>[] constructors = type.getDeclaredConstructors();
|
|
||||||
for (Constructor<?> constructor : constructors) {
|
|
||||||
if (constructor.getParameterCount() == 1) {
|
|
||||||
Class<?> cls = constructor.getParameterTypes()[0];
|
|
||||||
if (DeferredLogFactory.class.isAssignableFrom(cls)) {
|
|
||||||
return newInstance(constructor, logFactory);
|
|
||||||
}
|
|
||||||
if (Log.class.isAssignableFrom(cls)) {
|
|
||||||
return newInstance(constructor, logFactory.getLog(type));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (EnvironmentPostProcessor) ReflectionUtils.accessibleConstructor(type).newInstance();
|
|
||||||
}
|
|
||||||
|
|
||||||
private EnvironmentPostProcessor newInstance(Constructor<?> constructor, Object... initargs) throws Exception {
|
|
||||||
ReflectionUtils.makeAccessible(constructor);
|
|
||||||
return (EnvironmentPostProcessor) constructor.newInstance(initargs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,199 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2020 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.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import org.assertj.core.api.AbstractAssert;
|
||||||
|
import org.assertj.core.api.AssertProvider;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.env.BootstrapRegistry.Registration;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.context.support.StaticApplicationContext;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for {@link DefaultBootstrapRegisty}.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
class DefaultBootstrapRegistyTests {
|
||||||
|
|
||||||
|
private DefaultBootstrapRegisty registy = new DefaultBootstrapRegisty();
|
||||||
|
|
||||||
|
private AtomicInteger counter = new AtomicInteger();
|
||||||
|
|
||||||
|
private StaticApplicationContext context = new StaticApplicationContext();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getWhenNotRegisteredCreateInstance() {
|
||||||
|
Integer result = this.registy.get(Integer.class, this.counter::getAndIncrement);
|
||||||
|
assertThat(result).isEqualTo(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getWhenAlreadyRegisteredReturnsExisting() {
|
||||||
|
this.registy.get(Integer.class, this.counter::getAndIncrement);
|
||||||
|
Integer result = this.registy.get(Integer.class, this.counter::getAndIncrement);
|
||||||
|
assertThat(result).isEqualTo(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getWithPreparedActionRegistersAction() {
|
||||||
|
TestApplicationPreparedAction action = new TestApplicationPreparedAction();
|
||||||
|
Integer result = this.registy.get(Integer.class, this.counter::getAndIncrement, action::run);
|
||||||
|
this.registy.applicationContextPrepared(this.context);
|
||||||
|
assertThat(result).isEqualTo(0);
|
||||||
|
assertThat(action).wasCalledOnlyOnce().hasInstanceValue(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getWithPreparedActionWhenAlreadyRegisteredIgnoresRegistersAction() {
|
||||||
|
TestApplicationPreparedAction action1 = new TestApplicationPreparedAction();
|
||||||
|
TestApplicationPreparedAction action2 = new TestApplicationPreparedAction();
|
||||||
|
this.registy.get(Integer.class, this.counter::getAndIncrement, action1::run);
|
||||||
|
this.registy.get(Integer.class, this.counter::getAndIncrement, action2::run);
|
||||||
|
this.registy.applicationContextPrepared(this.context);
|
||||||
|
assertThat(action1).wasCalledOnlyOnce().hasInstanceValue(0);
|
||||||
|
assertThat(action2).wasNotCalled();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void registerAddsRegistration() {
|
||||||
|
Registration<Integer> registration = this.registy.register(Integer.class, this.counter::getAndIncrement);
|
||||||
|
assertThat(registration.get()).isEqualTo(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void registerWhenAlreadyRegisteredReplacesPreviousRegistration() {
|
||||||
|
Registration<Integer> registration1 = this.registy.register(Integer.class, this.counter::getAndIncrement);
|
||||||
|
Registration<Integer> registration2 = this.registy.register(Integer.class, () -> -1);
|
||||||
|
assertThat(registration2).isNotEqualTo(registration1);
|
||||||
|
assertThat(registration1.get()).isEqualTo(0);
|
||||||
|
assertThat(registration2.get()).isEqualTo(-1);
|
||||||
|
assertThat(this.registy.get(Integer.class, this.counter::getAndIncrement)).isEqualTo(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isRegisteredWhenNotRegisteredReturnsFalse() {
|
||||||
|
assertThat(this.registy.isRegistered(Integer.class)).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void isRegisteredWhenRegisteredReturnsTrue() {
|
||||||
|
this.registy.register(Integer.class, this.counter::getAndIncrement);
|
||||||
|
assertThat(this.registy.isRegistered(Integer.class)).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getRegistrationWhenNotRegisteredReturnsNull() {
|
||||||
|
assertThat(this.registy.getRegistration(Integer.class)).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getRegistrationWhenRegisteredReturnsRegistration() {
|
||||||
|
Registration<Integer> registration = this.registy.register(Integer.class, this.counter::getAndIncrement);
|
||||||
|
assertThat(this.registy.getRegistration(Integer.class)).isSameAs(registration);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void applicationContextPreparedTriggersActions() {
|
||||||
|
TestApplicationPreparedAction action1 = new TestApplicationPreparedAction();
|
||||||
|
TestApplicationPreparedAction action2 = new TestApplicationPreparedAction();
|
||||||
|
Registration<Integer> registration = this.registy.register(Integer.class, this.counter::getAndIncrement);
|
||||||
|
registration.onApplicationContextPrepared(action1::run);
|
||||||
|
registration.onApplicationContextPrepared(action2::run);
|
||||||
|
this.registy.applicationContextPrepared(this.context);
|
||||||
|
assertThat(action1).wasCalledOnlyOnce().hasInstanceValue(0);
|
||||||
|
assertThat(action2).wasCalledOnlyOnce().hasInstanceValue(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void registrationGetReturnsInstance() {
|
||||||
|
Registration<Integer> registration = this.registy.register(Integer.class, this.counter::getAndIncrement);
|
||||||
|
assertThat(registration.get()).isEqualTo(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void registrationGetWhenCalledMultipleTimesReturnsSingleInstance() {
|
||||||
|
Registration<Integer> registration = this.registy.register(Integer.class, this.counter::getAndIncrement);
|
||||||
|
assertThat(registration.get()).isEqualTo(0);
|
||||||
|
assertThat(registration.get()).isEqualTo(0);
|
||||||
|
assertThat(registration.get()).isEqualTo(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void registrationOnApplicationContextPreparedAddsAction() {
|
||||||
|
TestApplicationPreparedAction action = new TestApplicationPreparedAction();
|
||||||
|
Registration<Integer> registration = this.registy.register(Integer.class, this.counter::getAndIncrement);
|
||||||
|
registration.onApplicationContextPrepared(action::run);
|
||||||
|
this.registy.applicationContextPrepared(this.context);
|
||||||
|
assertThat(action).wasCalledOnlyOnce().hasInstanceValue(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void registrationOnApplicationContextPreparedWhenActionIsNullDoesNotAddAction() {
|
||||||
|
Registration<Integer> registration = this.registy.register(Integer.class, this.counter::getAndIncrement);
|
||||||
|
registration.onApplicationContextPrepared(null);
|
||||||
|
this.registy.applicationContextPrepared(this.context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TestApplicationPreparedAction implements AssertProvider<ApplicationPreparedActionAssert> {
|
||||||
|
|
||||||
|
private Integer instance;
|
||||||
|
|
||||||
|
private int called;
|
||||||
|
|
||||||
|
void run(ConfigurableApplicationContext context, Integer instance) {
|
||||||
|
this.instance = instance;
|
||||||
|
this.called++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApplicationPreparedActionAssert assertThat() {
|
||||||
|
return new ApplicationPreparedActionAssert(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ApplicationPreparedActionAssert
|
||||||
|
extends AbstractAssert<ApplicationPreparedActionAssert, TestApplicationPreparedAction> {
|
||||||
|
|
||||||
|
ApplicationPreparedActionAssert(TestApplicationPreparedAction actual) {
|
||||||
|
super(actual, ApplicationPreparedActionAssert.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplicationPreparedActionAssert hasInstanceValue(Integer expected) {
|
||||||
|
assertThat(this.actual.instance).isEqualTo(expected);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplicationPreparedActionAssert wasCalledOnlyOnce() {
|
||||||
|
assertThat(this.actual.called).as("action calls").isEqualTo(1);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplicationPreparedActionAssert wasNotCalled() {
|
||||||
|
assertThat(this.actual.called).as("action calls").isEqualTo(0);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -45,8 +45,11 @@ class EnvironmentPostProcessorApplicationListenerTests {
|
||||||
|
|
||||||
private DeferredLogs deferredLogs = spy(new DeferredLogs());
|
private DeferredLogs deferredLogs = spy(new DeferredLogs());
|
||||||
|
|
||||||
|
private DefaultBootstrapRegisty bootstrapRegistry = spy(new DefaultBootstrapRegisty());
|
||||||
|
|
||||||
private EnvironmentPostProcessorApplicationListener listener = new EnvironmentPostProcessorApplicationListener(
|
private EnvironmentPostProcessorApplicationListener listener = new EnvironmentPostProcessorApplicationListener(
|
||||||
EnvironmentPostProcessorsFactory.singleton(TestEnvironmentPostProcessor::new), this.deferredLogs);
|
EnvironmentPostProcessorsFactory.of(TestEnvironmentPostProcessor.class), this.deferredLogs,
|
||||||
|
this.bootstrapRegistry);
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void createUsesSpringFactories() {
|
void createUsesSpringFactories() {
|
||||||
|
|
@ -57,7 +60,7 @@ class EnvironmentPostProcessorApplicationListenerTests {
|
||||||
@Test
|
@Test
|
||||||
void createWhenHasFactoryUsesFactory() {
|
void createWhenHasFactoryUsesFactory() {
|
||||||
EnvironmentPostProcessorApplicationListener listener = new EnvironmentPostProcessorApplicationListener(
|
EnvironmentPostProcessorApplicationListener listener = new EnvironmentPostProcessorApplicationListener(
|
||||||
EnvironmentPostProcessorsFactory.singleton(TestEnvironmentPostProcessor::new));
|
EnvironmentPostProcessorsFactory.of(TestEnvironmentPostProcessor.class));
|
||||||
List<EnvironmentPostProcessor> postProcessors = listener.getEnvironmentPostProcessors();
|
List<EnvironmentPostProcessor> postProcessors = listener.getEnvironmentPostProcessors();
|
||||||
assertThat(postProcessors).hasSize(1);
|
assertThat(postProcessors).hasSize(1);
|
||||||
assertThat(postProcessors.get(0)).isInstanceOf(TestEnvironmentPostProcessor.class);
|
assertThat(postProcessors.get(0)).isInstanceOf(TestEnvironmentPostProcessor.class);
|
||||||
|
|
@ -102,6 +105,15 @@ class EnvironmentPostProcessorApplicationListenerTests {
|
||||||
verify(this.deferredLogs).switchOverAll();
|
verify(this.deferredLogs).switchOverAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void onApplicationEventWhenApplicationPreparedEventTriggersRegistryActions() {
|
||||||
|
SpringApplication application = mock(SpringApplication.class);
|
||||||
|
ConfigurableApplicationContext context = mock(ConfigurableApplicationContext.class);
|
||||||
|
ApplicationPreparedEvent event = new ApplicationPreparedEvent(application, new String[0], context);
|
||||||
|
this.listener.onApplicationEvent(event);
|
||||||
|
verify(this.bootstrapRegistry).applicationContextPrepared(context);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void onApplicationEventWhenApplicationFailedEventSwitchesLogs() {
|
void onApplicationEventWhenApplicationFailedEventSwitchesLogs() {
|
||||||
SpringApplication application = mock(SpringApplication.class);
|
SpringApplication application = mock(SpringApplication.class);
|
||||||
|
|
@ -114,7 +126,9 @@ class EnvironmentPostProcessorApplicationListenerTests {
|
||||||
|
|
||||||
static class TestEnvironmentPostProcessor implements EnvironmentPostProcessor {
|
static class TestEnvironmentPostProcessor implements EnvironmentPostProcessor {
|
||||||
|
|
||||||
TestEnvironmentPostProcessor(DeferredLogFactory logFactory) {
|
TestEnvironmentPostProcessor(DeferredLogFactory logFactory, BootstrapRegistry bootstrapRegistry) {
|
||||||
|
assertThat(logFactory).isNotNull();
|
||||||
|
assertThat(bootstrapRegistry).isNotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -36,10 +36,13 @@ class EnvironmentPostProcessorsFactoryTests {
|
||||||
|
|
||||||
private final DeferredLogFactory logFactory = Supplier::get;
|
private final DeferredLogFactory logFactory = Supplier::get;
|
||||||
|
|
||||||
|
private final BootstrapRegistry bootstrapRegistry = new DefaultBootstrapRegisty();
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void fromSpringFactoriesReturnsFactory() {
|
void fromSpringFactoriesReturnsFactory() {
|
||||||
EnvironmentPostProcessorsFactory factory = EnvironmentPostProcessorsFactory.fromSpringFactories(null);
|
EnvironmentPostProcessorsFactory factory = EnvironmentPostProcessorsFactory.fromSpringFactories(null);
|
||||||
List<EnvironmentPostProcessor> processors = factory.getEnvironmentPostProcessors(this.logFactory);
|
List<EnvironmentPostProcessor> processors = factory.getEnvironmentPostProcessors(this.logFactory,
|
||||||
|
this.bootstrapRegistry);
|
||||||
assertThat(processors).hasSizeGreaterThan(1);
|
assertThat(processors).hasSizeGreaterThan(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -47,7 +50,8 @@ class EnvironmentPostProcessorsFactoryTests {
|
||||||
void ofClassesReturnsFactory() {
|
void ofClassesReturnsFactory() {
|
||||||
EnvironmentPostProcessorsFactory factory = EnvironmentPostProcessorsFactory
|
EnvironmentPostProcessorsFactory factory = EnvironmentPostProcessorsFactory
|
||||||
.of(TestEnvironmentPostProcessor.class);
|
.of(TestEnvironmentPostProcessor.class);
|
||||||
List<EnvironmentPostProcessor> processors = factory.getEnvironmentPostProcessors(this.logFactory);
|
List<EnvironmentPostProcessor> processors = factory.getEnvironmentPostProcessors(this.logFactory,
|
||||||
|
this.bootstrapRegistry);
|
||||||
assertThat(processors).hasSize(1);
|
assertThat(processors).hasSize(1);
|
||||||
assertThat(processors.get(0)).isInstanceOf(TestEnvironmentPostProcessor.class);
|
assertThat(processors.get(0)).isInstanceOf(TestEnvironmentPostProcessor.class);
|
||||||
}
|
}
|
||||||
|
|
@ -56,16 +60,8 @@ class EnvironmentPostProcessorsFactoryTests {
|
||||||
void ofClassNamesReturnsFactory() {
|
void ofClassNamesReturnsFactory() {
|
||||||
EnvironmentPostProcessorsFactory factory = EnvironmentPostProcessorsFactory
|
EnvironmentPostProcessorsFactory factory = EnvironmentPostProcessorsFactory
|
||||||
.of(TestEnvironmentPostProcessor.class.getName());
|
.of(TestEnvironmentPostProcessor.class.getName());
|
||||||
List<EnvironmentPostProcessor> processors = factory.getEnvironmentPostProcessors(this.logFactory);
|
List<EnvironmentPostProcessor> processors = factory.getEnvironmentPostProcessors(this.logFactory,
|
||||||
assertThat(processors).hasSize(1);
|
this.bootstrapRegistry);
|
||||||
assertThat(processors.get(0)).isInstanceOf(TestEnvironmentPostProcessor.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void singletonReturnsFactory() {
|
|
||||||
EnvironmentPostProcessorsFactory factory = EnvironmentPostProcessorsFactory
|
|
||||||
.singleton(TestEnvironmentPostProcessor::new);
|
|
||||||
List<EnvironmentPostProcessor> processors = factory.getEnvironmentPostProcessors(this.logFactory);
|
|
||||||
assertThat(processors).hasSize(1);
|
assertThat(processors).hasSize(1);
|
||||||
assertThat(processors.get(0)).isInstanceOf(TestEnvironmentPostProcessor.class);
|
assertThat(processors.get(0)).isInstanceOf(TestEnvironmentPostProcessor.class);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,8 @@ class ReflectionEnvironmentPostProcessorsFactoryTests {
|
||||||
|
|
||||||
private final DeferredLogFactory logFactory = Supplier::get;
|
private final DeferredLogFactory logFactory = Supplier::get;
|
||||||
|
|
||||||
|
private final BootstrapRegistry bootstrapRegistry = new DefaultBootstrapRegisty();
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void createWithClassesCreatesFactory() {
|
void createWithClassesCreatesFactory() {
|
||||||
ReflectionEnvironmentPostProcessorsFactory factory = new ReflectionEnvironmentPostProcessorsFactory(
|
ReflectionEnvironmentPostProcessorsFactory factory = new ReflectionEnvironmentPostProcessorsFactory(
|
||||||
|
|
@ -82,11 +84,19 @@ class ReflectionEnvironmentPostProcessorsFactoryTests {
|
||||||
assertThatFactory(factory).createsSinglePostProcessor(TestLogEnvironmentPostProcessor.class);
|
assertThatFactory(factory).createsSinglePostProcessor(TestLogEnvironmentPostProcessor.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getEnvironmentPostProcessorsWhenHasBootstrapRegistryConstructorCreatesPostProcessors() {
|
||||||
|
ReflectionEnvironmentPostProcessorsFactory factory = new ReflectionEnvironmentPostProcessorsFactory(
|
||||||
|
TestBootstrapRegistryEnvironmentPostProcessor.class.getName());
|
||||||
|
assertThatFactory(factory).createsSinglePostProcessor(TestBootstrapRegistryEnvironmentPostProcessor.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void getEnvironmentPostProcessorsWhenHasNoSuitableConstructorThrowsException() {
|
void getEnvironmentPostProcessorsWhenHasNoSuitableConstructorThrowsException() {
|
||||||
ReflectionEnvironmentPostProcessorsFactory factory = new ReflectionEnvironmentPostProcessorsFactory(
|
ReflectionEnvironmentPostProcessorsFactory factory = new ReflectionEnvironmentPostProcessorsFactory(
|
||||||
BadEnvironmentPostProcessor.class.getName());
|
BadEnvironmentPostProcessor.class.getName());
|
||||||
assertThatIllegalArgumentException().isThrownBy(() -> factory.getEnvironmentPostProcessors(this.logFactory))
|
assertThatIllegalArgumentException()
|
||||||
|
.isThrownBy(() -> factory.getEnvironmentPostProcessors(this.logFactory, this.bootstrapRegistry))
|
||||||
.withMessageContaining("Unable to instantiate");
|
.withMessageContaining("Unable to instantiate");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -103,8 +113,9 @@ class ReflectionEnvironmentPostProcessorsFactoryTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
void createsSinglePostProcessor(Class<?> expectedType) {
|
void createsSinglePostProcessor(Class<?> expectedType) {
|
||||||
List<EnvironmentPostProcessor> processors = this.factory
|
List<EnvironmentPostProcessor> processors = this.factory.getEnvironmentPostProcessors(
|
||||||
.getEnvironmentPostProcessors(ReflectionEnvironmentPostProcessorsFactoryTests.this.logFactory);
|
ReflectionEnvironmentPostProcessorsFactoryTests.this.logFactory,
|
||||||
|
ReflectionEnvironmentPostProcessorsFactoryTests.this.bootstrapRegistry);
|
||||||
assertThat(processors).hasSize(1);
|
assertThat(processors).hasSize(1);
|
||||||
assertThat(processors.get(0)).isInstanceOf(expectedType);
|
assertThat(processors.get(0)).isInstanceOf(expectedType);
|
||||||
}
|
}
|
||||||
|
|
@ -143,6 +154,18 @@ class ReflectionEnvironmentPostProcessorsFactoryTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class TestBootstrapRegistryEnvironmentPostProcessor implements EnvironmentPostProcessor {
|
||||||
|
|
||||||
|
TestBootstrapRegistryEnvironmentPostProcessor(BootstrapRegistry bootstrapRegistry) {
|
||||||
|
assertThat(bootstrapRegistry).isNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static class BadEnvironmentPostProcessor implements EnvironmentPostProcessor {
|
static class BadEnvironmentPostProcessor implements EnvironmentPostProcessor {
|
||||||
|
|
||||||
BadEnvironmentPostProcessor(InputStream inputStream) {
|
BadEnvironmentPostProcessor(InputStream inputStream) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue