mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-08-29 03:06:45 +08:00
Add BootstrapRegisty support for config data
Expose the `BootstrapRegisty` to both `ConfigDataLocationResolver` and `ConfigDataLoader` implementations. The registry is exposed via the context interfaces and may be used to reuse instances that are expensive to create. It may also be used to ultimately register beans with the `ApplicationContext`. Closes gh-22956
This commit is contained in:
parent
2260657781
commit
d123c924a0
@ -18,6 +18,7 @@ package org.springframework.boot.test.context;
|
|||||||
|
|
||||||
import org.springframework.boot.context.config.ConfigData;
|
import org.springframework.boot.context.config.ConfigData;
|
||||||
import org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor;
|
import org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor;
|
||||||
|
import org.springframework.boot.env.DefaultBootstrapRegisty;
|
||||||
import org.springframework.boot.env.DefaultPropertiesPropertySource;
|
import org.springframework.boot.env.DefaultPropertiesPropertySource;
|
||||||
import org.springframework.boot.env.RandomValuePropertySource;
|
import org.springframework.boot.env.RandomValuePropertySource;
|
||||||
import org.springframework.context.ApplicationContextInitializer;
|
import org.springframework.context.ApplicationContextInitializer;
|
||||||
@ -41,7 +42,9 @@ public class ConfigDataApplicationContextInitializer
|
|||||||
public void initialize(ConfigurableApplicationContext applicationContext) {
|
public void initialize(ConfigurableApplicationContext applicationContext) {
|
||||||
ConfigurableEnvironment environment = applicationContext.getEnvironment();
|
ConfigurableEnvironment environment = applicationContext.getEnvironment();
|
||||||
RandomValuePropertySource.addToEnvironment(environment);
|
RandomValuePropertySource.addToEnvironment(environment);
|
||||||
ConfigDataEnvironmentPostProcessor.applyTo(environment, applicationContext);
|
DefaultBootstrapRegisty bootstrapRegistry = new DefaultBootstrapRegisty();
|
||||||
|
ConfigDataEnvironmentPostProcessor.applyTo(environment, applicationContext, bootstrapRegistry);
|
||||||
|
bootstrapRegistry.applicationContextPrepared(applicationContext);
|
||||||
DefaultPropertiesPropertySource.moveToEnd(environment);
|
DefaultPropertiesPropertySource.moveToEnd(environment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ import org.apache.commons.logging.Log;
|
|||||||
import org.springframework.boot.context.config.ConfigDataEnvironmentContributors.BinderOption;
|
import org.springframework.boot.context.config.ConfigDataEnvironmentContributors.BinderOption;
|
||||||
import org.springframework.boot.context.properties.bind.BindException;
|
import org.springframework.boot.context.properties.bind.BindException;
|
||||||
import org.springframework.boot.context.properties.bind.Binder;
|
import org.springframework.boot.context.properties.bind.Binder;
|
||||||
|
import org.springframework.boot.env.BootstrapRegistry;
|
||||||
import org.springframework.boot.env.DefaultPropertiesPropertySource;
|
import org.springframework.boot.env.DefaultPropertiesPropertySource;
|
||||||
import org.springframework.boot.logging.DeferredLogFactory;
|
import org.springframework.boot.logging.DeferredLogFactory;
|
||||||
import org.springframework.core.env.ConfigurableEnvironment;
|
import org.springframework.core.env.ConfigurableEnvironment;
|
||||||
@ -77,6 +78,8 @@ class ConfigDataEnvironment {
|
|||||||
|
|
||||||
private final Log logger;
|
private final Log logger;
|
||||||
|
|
||||||
|
private final BootstrapRegistry bootstrapRegistry;
|
||||||
|
|
||||||
private final ConfigurableEnvironment environment;
|
private final ConfigurableEnvironment environment;
|
||||||
|
|
||||||
private final ConfigDataLocationResolvers resolvers;
|
private final ConfigDataLocationResolvers resolvers;
|
||||||
@ -90,16 +93,18 @@ class ConfigDataEnvironment {
|
|||||||
/**
|
/**
|
||||||
* Create a new {@link ConfigDataEnvironment} instance.
|
* Create a new {@link ConfigDataEnvironment} instance.
|
||||||
* @param logFactory the deferred log factory
|
* @param logFactory the deferred log factory
|
||||||
|
* @param bootstrapRegistry the bootstrap registry
|
||||||
* @param environment the Spring {@link Environment}.
|
* @param environment the Spring {@link Environment}.
|
||||||
* @param resourceLoader {@link ResourceLoader} to load resource locations
|
* @param resourceLoader {@link ResourceLoader} to load resource locations
|
||||||
* @param additionalProfiles any additional profiles to activate
|
* @param additionalProfiles any additional profiles to activate
|
||||||
*/
|
*/
|
||||||
ConfigDataEnvironment(DeferredLogFactory logFactory, ConfigurableEnvironment environment,
|
ConfigDataEnvironment(DeferredLogFactory logFactory, BootstrapRegistry bootstrapRegistry,
|
||||||
ResourceLoader resourceLoader, Collection<String> additionalProfiles) {
|
ConfigurableEnvironment environment, ResourceLoader resourceLoader, Collection<String> additionalProfiles) {
|
||||||
Binder binder = Binder.get(environment);
|
Binder binder = Binder.get(environment);
|
||||||
UseLegacyConfigProcessingException.throwIfRequested(binder);
|
UseLegacyConfigProcessingException.throwIfRequested(binder);
|
||||||
this.logFactory = logFactory;
|
this.logFactory = logFactory;
|
||||||
this.logger = logFactory.getLog(getClass());
|
this.logger = logFactory.getLog(getClass());
|
||||||
|
this.bootstrapRegistry = bootstrapRegistry;
|
||||||
this.environment = environment;
|
this.environment = environment;
|
||||||
this.resolvers = createConfigDataLocationResolvers(logFactory, binder, resourceLoader);
|
this.resolvers = createConfigDataLocationResolvers(logFactory, binder, resourceLoader);
|
||||||
this.additionalProfiles = additionalProfiles;
|
this.additionalProfiles = additionalProfiles;
|
||||||
@ -132,7 +137,7 @@ class ConfigDataEnvironment {
|
|||||||
this.logger.trace("Creating wrapped config data contributor for default property source");
|
this.logger.trace("Creating wrapped config data contributor for default property source");
|
||||||
contributors.add(ConfigDataEnvironmentContributor.ofExisting(defaultPropertySource));
|
contributors.add(ConfigDataEnvironmentContributor.ofExisting(defaultPropertySource));
|
||||||
}
|
}
|
||||||
return new ConfigDataEnvironmentContributors(this.logFactory, contributors);
|
return new ConfigDataEnvironmentContributors(this.logFactory, this.bootstrapRegistry, contributors);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigDataEnvironmentContributors getContributors() {
|
ConfigDataEnvironmentContributors getContributors() {
|
||||||
|
@ -36,6 +36,7 @@ import org.springframework.boot.context.properties.bind.Binder;
|
|||||||
import org.springframework.boot.context.properties.bind.PlaceholdersResolver;
|
import org.springframework.boot.context.properties.bind.PlaceholdersResolver;
|
||||||
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
|
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
|
||||||
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
|
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
|
||||||
|
import org.springframework.boot.env.BootstrapRegistry;
|
||||||
import org.springframework.boot.logging.DeferredLogFactory;
|
import org.springframework.boot.logging.DeferredLogFactory;
|
||||||
import org.springframework.core.log.LogMessage;
|
import org.springframework.core.log.LogMessage;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
@ -53,19 +54,25 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen
|
|||||||
|
|
||||||
private final ConfigDataEnvironmentContributor root;
|
private final ConfigDataEnvironmentContributor root;
|
||||||
|
|
||||||
|
private final BootstrapRegistry bootstrapRegistry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new {@link ConfigDataEnvironmentContributors} instance.
|
* Create a new {@link ConfigDataEnvironmentContributors} instance.
|
||||||
* @param logFactory the log factory
|
* @param logFactory the log factory
|
||||||
|
* @param bootstrapRegistry the bootstrap registry
|
||||||
* @param contributors the initial set of contributors
|
* @param contributors the initial set of contributors
|
||||||
*/
|
*/
|
||||||
ConfigDataEnvironmentContributors(DeferredLogFactory logFactory,
|
ConfigDataEnvironmentContributors(DeferredLogFactory logFactory, BootstrapRegistry bootstrapRegistry,
|
||||||
List<ConfigDataEnvironmentContributor> contributors) {
|
List<ConfigDataEnvironmentContributor> contributors) {
|
||||||
this.logger = logFactory.getLog(getClass());
|
this.logger = logFactory.getLog(getClass());
|
||||||
|
this.bootstrapRegistry = bootstrapRegistry;
|
||||||
this.root = ConfigDataEnvironmentContributor.of(contributors);
|
this.root = ConfigDataEnvironmentContributor.of(contributors);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConfigDataEnvironmentContributors(Log logger, ConfigDataEnvironmentContributor root) {
|
private ConfigDataEnvironmentContributors(Log logger, BootstrapRegistry bootstrapRegistry,
|
||||||
|
ConfigDataEnvironmentContributor root) {
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
|
this.bootstrapRegistry = bootstrapRegistry;
|
||||||
this.root = root;
|
this.root = root;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,22 +98,27 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen
|
|||||||
this.logger.trace(LogMessage.format("Processed imports for of %d contributors", processedCount));
|
this.logger.trace(LogMessage.format("Processed imports for of %d contributors", processedCount));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
ConfigDataLocationResolverContext locationResolverContext = new ContributorLocationResolverContext(result,
|
ConfigDataLocationResolverContext locationResolverContext = new ContributorConfigDataLocationResolverContext(
|
||||||
unprocessed, activationContext);
|
result, unprocessed, activationContext);
|
||||||
|
ConfigDataLoaderContext loaderContext = new ContributorDataLoaderContext(this);
|
||||||
List<String> imports = unprocessed.getImports();
|
List<String> imports = unprocessed.getImports();
|
||||||
this.logger.trace(LogMessage.format("Processing imports %s", imports));
|
this.logger.trace(LogMessage.format("Processing imports %s", imports));
|
||||||
Map<ConfigDataLocation, ConfigData> imported = importer.resolveAndLoad(activationContext,
|
Map<ConfigDataLocation, ConfigData> imported = importer.resolveAndLoad(activationContext,
|
||||||
locationResolverContext, imports);
|
locationResolverContext, loaderContext, imports);
|
||||||
this.logger.trace(LogMessage.of(() -> imported.isEmpty() ? "Nothing imported" : "Imported "
|
this.logger.trace(LogMessage.of(() -> imported.isEmpty() ? "Nothing imported" : "Imported "
|
||||||
+ imported.size() + " location " + ((imported.size() != 1) ? "s" : "") + imported.keySet()));
|
+ imported.size() + " location " + ((imported.size() != 1) ? "s" : "") + imported.keySet()));
|
||||||
ConfigDataEnvironmentContributor processed = unprocessed.withChildren(importPhase,
|
ConfigDataEnvironmentContributor processed = unprocessed.withChildren(importPhase,
|
||||||
asContributors(activationContext, imported));
|
asContributors(activationContext, imported));
|
||||||
result = new ConfigDataEnvironmentContributors(this.logger,
|
result = new ConfigDataEnvironmentContributors(this.logger, this.bootstrapRegistry,
|
||||||
result.getRoot().withReplacement(unprocessed, processed));
|
result.getRoot().withReplacement(unprocessed, processed));
|
||||||
processedCount++;
|
processedCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected final BootstrapRegistry getBootstrapRegistry() {
|
||||||
|
return this.bootstrapRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
private ConfigDataEnvironmentContributor getFirstUnprocessed(ConfigDataEnvironmentContributors contributors,
|
private ConfigDataEnvironmentContributor getFirstUnprocessed(ConfigDataEnvironmentContributors contributors,
|
||||||
ConfigDataActivationContext activationContext, ImportPhase importPhase) {
|
ConfigDataActivationContext activationContext, ImportPhase importPhase) {
|
||||||
for (ConfigDataEnvironmentContributor contributor : contributors.getRoot()) {
|
for (ConfigDataEnvironmentContributor contributor : contributors.getRoot()) {
|
||||||
@ -177,10 +189,27 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link ConfigDataLocationResolverContext} backed by a
|
* {@link ConfigDataLocationResolverContext} for a contributor.
|
||||||
* {@link ConfigDataEnvironmentContributor}.
|
|
||||||
*/
|
*/
|
||||||
private static class ContributorLocationResolverContext implements ConfigDataLocationResolverContext {
|
private static class ContributorDataLoaderContext implements ConfigDataLoaderContext {
|
||||||
|
|
||||||
|
private final ConfigDataEnvironmentContributors contributors;
|
||||||
|
|
||||||
|
ContributorDataLoaderContext(ConfigDataEnvironmentContributors contributors) {
|
||||||
|
this.contributors = contributors;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BootstrapRegistry getBootstrapRegistry() {
|
||||||
|
return this.contributors.getBootstrapRegistry();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link ConfigDataLocationResolverContext} for a contributor.
|
||||||
|
*/
|
||||||
|
private static class ContributorConfigDataLocationResolverContext implements ConfigDataLocationResolverContext {
|
||||||
|
|
||||||
private final ConfigDataEnvironmentContributors contributors;
|
private final ConfigDataEnvironmentContributors contributors;
|
||||||
|
|
||||||
@ -190,7 +219,7 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen
|
|||||||
|
|
||||||
private volatile Binder binder;
|
private volatile Binder binder;
|
||||||
|
|
||||||
ContributorLocationResolverContext(ConfigDataEnvironmentContributors contributors,
|
ContributorConfigDataLocationResolverContext(ConfigDataEnvironmentContributors contributors,
|
||||||
ConfigDataEnvironmentContributor contributor, ConfigDataActivationContext activationContext) {
|
ConfigDataEnvironmentContributor contributor, ConfigDataActivationContext activationContext) {
|
||||||
this.contributors = contributors;
|
this.contributors = contributors;
|
||||||
this.contributor = contributor;
|
this.contributor = contributor;
|
||||||
@ -212,6 +241,11 @@ class ConfigDataEnvironmentContributors implements Iterable<ConfigDataEnvironmen
|
|||||||
return this.contributor.getLocation();
|
return this.contributor.getLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BootstrapRegistry getBootstrapRegistry() {
|
||||||
|
return this.contributors.getBootstrapRegistry();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class InactiveSourceChecker implements BindHandler {
|
private class InactiveSourceChecker implements BindHandler {
|
||||||
|
@ -24,6 +24,8 @@ import java.util.function.Supplier;
|
|||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.env.BootstrapRegistry;
|
||||||
|
import org.springframework.boot.env.DefaultBootstrapRegisty;
|
||||||
import org.springframework.boot.env.EnvironmentPostProcessor;
|
import org.springframework.boot.env.EnvironmentPostProcessor;
|
||||||
import org.springframework.boot.logging.DeferredLogFactory;
|
import org.springframework.boot.logging.DeferredLogFactory;
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.core.Ordered;
|
||||||
@ -52,9 +54,12 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces
|
|||||||
|
|
||||||
private final Log logger;
|
private final Log logger;
|
||||||
|
|
||||||
public ConfigDataEnvironmentPostProcessor(DeferredLogFactory logFactory) {
|
private final BootstrapRegistry bootstrapRegistry;
|
||||||
|
|
||||||
|
public ConfigDataEnvironmentPostProcessor(DeferredLogFactory logFactory, BootstrapRegistry bootstrapRegistry) {
|
||||||
this.logFactory = logFactory;
|
this.logFactory = logFactory;
|
||||||
this.logger = logFactory.getLog(getClass());
|
this.logger = logFactory.getLog(getClass());
|
||||||
|
this.bootstrapRegistry = bootstrapRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -83,7 +88,8 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces
|
|||||||
|
|
||||||
ConfigDataEnvironment getConfigDataEnvironment(ConfigurableEnvironment environment, ResourceLoader resourceLoader,
|
ConfigDataEnvironment getConfigDataEnvironment(ConfigurableEnvironment environment, ResourceLoader resourceLoader,
|
||||||
Collection<String> additionalProfiles) {
|
Collection<String> additionalProfiles) {
|
||||||
return new ConfigDataEnvironment(this.logFactory, environment, resourceLoader, additionalProfiles);
|
return new ConfigDataEnvironment(this.logFactory, this.bootstrapRegistry, environment, resourceLoader,
|
||||||
|
additionalProfiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void postProcessUsingLegacyApplicationListener(ConfigurableEnvironment environment,
|
private void postProcessUsingLegacyApplicationListener(ConfigurableEnvironment environment,
|
||||||
@ -103,7 +109,7 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces
|
|||||||
* @param environment the environment to apply {@link ConfigData} to
|
* @param environment the environment to apply {@link ConfigData} to
|
||||||
*/
|
*/
|
||||||
public static void applyTo(ConfigurableEnvironment environment) {
|
public static void applyTo(ConfigurableEnvironment environment) {
|
||||||
applyTo(environment, null, Collections.emptyList());
|
applyTo(environment, null, null, Collections.emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -112,11 +118,13 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces
|
|||||||
* directly and not necessarily as part of a {@link SpringApplication}.
|
* directly and not necessarily as part of a {@link SpringApplication}.
|
||||||
* @param environment the environment to apply {@link ConfigData} to
|
* @param environment the environment to apply {@link ConfigData} to
|
||||||
* @param resourceLoader the resource loader to use
|
* @param resourceLoader the resource loader to use
|
||||||
|
* @param bootstrapRegistry the bootstrap registry to use or {@code null} to use a
|
||||||
|
* throw-away registry
|
||||||
* @param additionalProfiles any additional profiles that should be applied
|
* @param additionalProfiles any additional profiles that should be applied
|
||||||
*/
|
*/
|
||||||
public static void applyTo(ConfigurableEnvironment environment, ResourceLoader resourceLoader,
|
public static void applyTo(ConfigurableEnvironment environment, ResourceLoader resourceLoader,
|
||||||
String... additionalProfiles) {
|
BootstrapRegistry bootstrapRegistry, String... additionalProfiles) {
|
||||||
applyTo(environment, resourceLoader, Arrays.asList(additionalProfiles));
|
applyTo(environment, resourceLoader, bootstrapRegistry, Arrays.asList(additionalProfiles));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -125,13 +133,17 @@ public class ConfigDataEnvironmentPostProcessor implements EnvironmentPostProces
|
|||||||
* directly and not necessarily as part of a {@link SpringApplication}.
|
* directly and not necessarily as part of a {@link SpringApplication}.
|
||||||
* @param environment the environment to apply {@link ConfigData} to
|
* @param environment the environment to apply {@link ConfigData} to
|
||||||
* @param resourceLoader the resource loader to use
|
* @param resourceLoader the resource loader to use
|
||||||
|
* @param bootstrapRegistry the bootstrap registry to use or {@code null} to use a
|
||||||
|
* throw-away registry
|
||||||
* @param additionalProfiles any additional profiles that should be applied
|
* @param additionalProfiles any additional profiles that should be applied
|
||||||
*/
|
*/
|
||||||
public static void applyTo(ConfigurableEnvironment environment, ResourceLoader resourceLoader,
|
public static void applyTo(ConfigurableEnvironment environment, ResourceLoader resourceLoader,
|
||||||
Collection<String> additionalProfiles) {
|
BootstrapRegistry bootstrapRegistry, Collection<String> additionalProfiles) {
|
||||||
new ConfigDataEnvironmentPostProcessor(Supplier::get).postProcessEnvironment(environment, resourceLoader,
|
DeferredLogFactory logFactory = Supplier::get;
|
||||||
additionalProfiles);
|
bootstrapRegistry = (bootstrapRegistry != null) ? bootstrapRegistry : new DefaultBootstrapRegisty();
|
||||||
|
ConfigDataEnvironmentPostProcessor postProcessor = new ConfigDataEnvironmentPostProcessor(logFactory,
|
||||||
|
bootstrapRegistry);
|
||||||
|
postProcessor.postProcessEnvironment(environment, resourceLoader, additionalProfiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
|
@ -55,26 +55,29 @@ class ConfigDataImporter {
|
|||||||
* previously loaded.
|
* previously loaded.
|
||||||
* @param activationContext the activation context
|
* @param activationContext the activation context
|
||||||
* @param locationResolverContext the location resolver context
|
* @param locationResolverContext the location resolver context
|
||||||
|
* @param loaderContext the loader context
|
||||||
* @param locations the locations to resolve
|
* @param locations the locations to resolve
|
||||||
* @return a map of the loaded locations and data
|
* @return a map of the loaded locations and data
|
||||||
*/
|
*/
|
||||||
Map<ConfigDataLocation, ConfigData> resolveAndLoad(ConfigDataActivationContext activationContext,
|
Map<ConfigDataLocation, ConfigData> resolveAndLoad(ConfigDataActivationContext activationContext,
|
||||||
ConfigDataLocationResolverContext locationResolverContext, List<String> locations) {
|
ConfigDataLocationResolverContext locationResolverContext, ConfigDataLoaderContext loaderContext,
|
||||||
|
List<String> locations) {
|
||||||
try {
|
try {
|
||||||
Profiles profiles = (activationContext != null) ? activationContext.getProfiles() : null;
|
Profiles profiles = (activationContext != null) ? activationContext.getProfiles() : null;
|
||||||
return load(this.resolvers.resolveAll(locationResolverContext, locations, profiles));
|
return load(loaderContext, this.resolvers.resolveAll(locationResolverContext, locations, profiles));
|
||||||
}
|
}
|
||||||
catch (IOException ex) {
|
catch (IOException ex) {
|
||||||
throw new IllegalStateException("IO error on loading imports from " + locations, ex);
|
throw new IllegalStateException("IO error on loading imports from " + locations, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<ConfigDataLocation, ConfigData> load(List<ConfigDataLocation> locations) throws IOException {
|
private Map<ConfigDataLocation, ConfigData> load(ConfigDataLoaderContext loaderContext,
|
||||||
|
List<ConfigDataLocation> locations) throws IOException {
|
||||||
Map<ConfigDataLocation, ConfigData> result = new LinkedHashMap<>();
|
Map<ConfigDataLocation, ConfigData> result = new LinkedHashMap<>();
|
||||||
for (int i = locations.size() - 1; i >= 0; i--) {
|
for (int i = locations.size() - 1; i >= 0; i--) {
|
||||||
ConfigDataLocation location = locations.get(i);
|
ConfigDataLocation location = locations.get(i);
|
||||||
if (this.loadedLocations.add(location)) {
|
if (this.loadedLocations.add(location)) {
|
||||||
result.put(location, this.loaders.load(location));
|
result.put(location, this.loaders.load(loaderContext, location));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Collections.unmodifiableMap(result);
|
return Collections.unmodifiableMap(result);
|
||||||
|
@ -40,19 +40,21 @@ public interface ConfigDataLoader<L extends ConfigDataLocation> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns if the specified location can be loaded by this instance.
|
* Returns if the specified location can be loaded by this instance.
|
||||||
|
* @param context the loader context
|
||||||
* @param location the location to check.
|
* @param location the location to check.
|
||||||
* @return if the location is supported by this loader
|
* @return if the location is supported by this loader
|
||||||
*/
|
*/
|
||||||
default boolean isLoadable(L location) {
|
default boolean isLoadable(ConfigDataLoaderContext context, L location) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load {@link ConfigData} for the given location.
|
* Load {@link ConfigData} for the given location.
|
||||||
|
* @param context the loader context
|
||||||
* @param location the location to load
|
* @param location the location to load
|
||||||
* @return the loaded config data or {@code null} if the location should be skipped
|
* @return the loaded config data or {@code null} if the location should be skipped
|
||||||
* @throws IOException on IO error
|
* @throws IOException on IO error
|
||||||
*/
|
*/
|
||||||
ConfigData load(L location) throws IOException;
|
ConfigData load(ConfigDataLoaderContext context, L location) throws IOException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* 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.context.config;
|
||||||
|
|
||||||
|
import org.springframework.boot.env.BootstrapRegistry;
|
||||||
|
import org.springframework.boot.env.EnvironmentPostProcessor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context provided to {@link ConfigDataLoader} methods.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @since 2.4.0
|
||||||
|
*/
|
||||||
|
public interface ConfigDataLoaderContext {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides access to the {@link BootstrapRegistry} shared across all
|
||||||
|
* {@link EnvironmentPostProcessor EnvironmentPostProcessors}.
|
||||||
|
* @return the bootstrap registry
|
||||||
|
*/
|
||||||
|
BootstrapRegistry getBootstrapRegistry();
|
||||||
|
|
||||||
|
}
|
@ -80,24 +80,25 @@ class ConfigDataLoaders {
|
|||||||
/**
|
/**
|
||||||
* Load {@link ConfigData} using the first appropriate {@link ConfigDataLoader}.
|
* Load {@link ConfigData} using the first appropriate {@link ConfigDataLoader}.
|
||||||
* @param <L> the config data location type
|
* @param <L> the config data location type
|
||||||
|
* @param context the loader context
|
||||||
* @param location the location to load
|
* @param location the location to load
|
||||||
* @return the loaded {@link ConfigData}
|
* @return the loaded {@link ConfigData}
|
||||||
* @throws IOException on IO error
|
* @throws IOException on IO error
|
||||||
*/
|
*/
|
||||||
<L extends ConfigDataLocation> ConfigData load(L location) throws IOException {
|
<L extends ConfigDataLocation> ConfigData load(ConfigDataLoaderContext context, L location) throws IOException {
|
||||||
ConfigDataLoader<L> loader = getLoader(location);
|
ConfigDataLoader<L> loader = getLoader(context, location);
|
||||||
this.logger.trace(LogMessage.of(() -> "Loading " + location + " using loader " + loader.getClass().getName()));
|
this.logger.trace(LogMessage.of(() -> "Loading " + location + " using loader " + loader.getClass().getName()));
|
||||||
return loader.load(location);
|
return loader.load(context, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private <L extends ConfigDataLocation> ConfigDataLoader<L> getLoader(L location) {
|
private <L extends ConfigDataLocation> ConfigDataLoader<L> getLoader(ConfigDataLoaderContext context, L location) {
|
||||||
ConfigDataLoader<L> result = null;
|
ConfigDataLoader<L> result = null;
|
||||||
for (int i = 0; i < this.loaders.size(); i++) {
|
for (int i = 0; i < this.loaders.size(); i++) {
|
||||||
ConfigDataLoader<?> candidate = this.loaders.get(i);
|
ConfigDataLoader<?> candidate = this.loaders.get(i);
|
||||||
if (this.locationTypes.get(i).isInstance(location)) {
|
if (this.locationTypes.get(i).isInstance(location)) {
|
||||||
ConfigDataLoader<L> loader = (ConfigDataLoader<L>) candidate;
|
ConfigDataLoader<L> loader = (ConfigDataLoader<L>) candidate;
|
||||||
if (loader.isLoadable(location)) {
|
if (loader.isLoadable(context, location)) {
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
throw new IllegalStateException("Multiple loaders found for location " + location + " ["
|
throw new IllegalStateException("Multiple loaders found for location " + location + " ["
|
||||||
+ candidate.getClass().getName() + "," + result.getClass().getName() + "]");
|
+ candidate.getClass().getName() + "," + result.getClass().getName() + "]");
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
package org.springframework.boot.context.config;
|
package org.springframework.boot.context.config;
|
||||||
|
|
||||||
import org.springframework.boot.context.properties.bind.Binder;
|
import org.springframework.boot.context.properties.bind.Binder;
|
||||||
|
import org.springframework.boot.env.BootstrapRegistry;
|
||||||
|
import org.springframework.boot.env.EnvironmentPostProcessor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Context provided to {@link ConfigDataLocationResolver} methods.
|
* Context provided to {@link ConfigDataLocationResolver} methods.
|
||||||
@ -41,4 +43,11 @@ public interface ConfigDataLocationResolverContext {
|
|||||||
*/
|
*/
|
||||||
ConfigDataLocation getParent();
|
ConfigDataLocation getParent();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides access to the {@link BootstrapRegistry} shared across all
|
||||||
|
* {@link EnvironmentPostProcessor EnvironmentPostProcessors}.
|
||||||
|
* @return the bootstrap registry
|
||||||
|
*/
|
||||||
|
BootstrapRegistry getBootstrapRegistry();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ import org.springframework.boot.env.ConfigTreePropertySource;
|
|||||||
class ConfigTreeConfigDataLoader implements ConfigDataLoader<ConfigTreeConfigDataLocation> {
|
class ConfigTreeConfigDataLoader implements ConfigDataLoader<ConfigTreeConfigDataLocation> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConfigData load(ConfigTreeConfigDataLocation location) throws IOException {
|
public ConfigData load(ConfigDataLoaderContext context, ConfigTreeConfigDataLocation location) throws IOException {
|
||||||
Path path = location.getPath();
|
Path path = location.getPath();
|
||||||
String name = "Config tree '" + path + "'";
|
String name = "Config tree '" + path + "'";
|
||||||
ConfigTreePropertySource source = new ConfigTreePropertySource(name, path);
|
ConfigTreePropertySource source = new ConfigTreePropertySource(name, path);
|
||||||
|
@ -29,7 +29,7 @@ import org.springframework.core.io.Resource;
|
|||||||
class ResourceConfigDataLoader implements ConfigDataLoader<ResourceConfigDataLocation> {
|
class ResourceConfigDataLoader implements ConfigDataLoader<ResourceConfigDataLocation> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConfigData load(ResourceConfigDataLocation location) throws IOException {
|
public ConfigData load(ConfigDataLoaderContext context, ResourceConfigDataLocation location) throws IOException {
|
||||||
return new ConfigData(location.load());
|
return new ConfigData(location.load());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,6 +80,13 @@ public class DefaultBootstrapRegisty implements BootstrapRegistry {
|
|||||||
.forEach((registration) -> registration.applicationContextPrepared(applicationContext));
|
.forEach((registration) -> registration.applicationContextPrepared(applicationContext));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the registry to reclaim memory.
|
||||||
|
*/
|
||||||
|
public void clear() {
|
||||||
|
this.registrations.clear();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default implementation of {@link Registration}.
|
* Default implementation of {@link Registration}.
|
||||||
*/
|
*/
|
||||||
|
@ -104,11 +104,16 @@ public class EnvironmentPostProcessorApplicationListener implements SmartApplica
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void onApplicationPreparedEvent(ApplicationPreparedEvent event) {
|
private void onApplicationPreparedEvent(ApplicationPreparedEvent event) {
|
||||||
this.deferredLogs.switchOverAll();
|
|
||||||
this.bootstrapRegistry.applicationContextPrepared(event.getApplicationContext());
|
this.bootstrapRegistry.applicationContextPrepared(event.getApplicationContext());
|
||||||
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onApplicationFailedEvent(ApplicationFailedEvent event) {
|
private void onApplicationFailedEvent(ApplicationFailedEvent event) {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void finish() {
|
||||||
|
this.bootstrapRegistry.clear();
|
||||||
this.deferredLogs.switchOverAll();
|
this.deferredLogs.switchOverAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,8 @@ import org.springframework.boot.context.config.ConfigDataEnvironmentContributor.
|
|||||||
import org.springframework.boot.context.config.ConfigDataEnvironmentContributors.BinderOption;
|
import org.springframework.boot.context.config.ConfigDataEnvironmentContributors.BinderOption;
|
||||||
import org.springframework.boot.context.properties.bind.BindException;
|
import org.springframework.boot.context.properties.bind.BindException;
|
||||||
import org.springframework.boot.context.properties.bind.Binder;
|
import org.springframework.boot.context.properties.bind.Binder;
|
||||||
|
import org.springframework.boot.env.BootstrapRegistry;
|
||||||
|
import org.springframework.boot.env.DefaultBootstrapRegisty;
|
||||||
import org.springframework.boot.logging.DeferredLogFactory;
|
import org.springframework.boot.logging.DeferredLogFactory;
|
||||||
import org.springframework.mock.env.MockEnvironment;
|
import org.springframework.mock.env.MockEnvironment;
|
||||||
import org.springframework.mock.env.MockPropertySource;
|
import org.springframework.mock.env.MockPropertySource;
|
||||||
@ -58,6 +60,8 @@ class ConfigDataEnvironmentContributorsTests {
|
|||||||
|
|
||||||
private DeferredLogFactory logFactory = Supplier::get;
|
private DeferredLogFactory logFactory = Supplier::get;
|
||||||
|
|
||||||
|
private BootstrapRegistry bootstrapRegistry = new DefaultBootstrapRegisty();
|
||||||
|
|
||||||
private MockEnvironment environment;
|
private MockEnvironment environment;
|
||||||
|
|
||||||
private Binder binder;
|
private Binder binder;
|
||||||
@ -69,6 +73,9 @@ class ConfigDataEnvironmentContributorsTests {
|
|||||||
@Captor
|
@Captor
|
||||||
private ArgumentCaptor<ConfigDataLocationResolverContext> locationResolverContext;
|
private ArgumentCaptor<ConfigDataLocationResolverContext> locationResolverContext;
|
||||||
|
|
||||||
|
@Captor
|
||||||
|
private ArgumentCaptor<ConfigDataLoaderContext> loaderContext;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setup() {
|
void setup() {
|
||||||
this.environment = new MockEnvironment();
|
this.environment = new MockEnvironment();
|
||||||
@ -83,7 +90,7 @@ class ConfigDataEnvironmentContributorsTests {
|
|||||||
void createCreatesWithInitialContributors() {
|
void createCreatesWithInitialContributors() {
|
||||||
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofInitialImport("test");
|
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofInitialImport("test");
|
||||||
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
||||||
Arrays.asList(contributor));
|
this.bootstrapRegistry, Arrays.asList(contributor));
|
||||||
Iterator<ConfigDataEnvironmentContributor> iterator = contributors.iterator();
|
Iterator<ConfigDataEnvironmentContributor> iterator = contributors.iterator();
|
||||||
assertThat(iterator.next()).isSameAs(contributor);
|
assertThat(iterator.next()).isSameAs(contributor);
|
||||||
assertThat(iterator.next().getKind()).isEqualTo(Kind.ROOT);
|
assertThat(iterator.next().getKind()).isEqualTo(Kind.ROOT);
|
||||||
@ -94,7 +101,7 @@ class ConfigDataEnvironmentContributorsTests {
|
|||||||
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor
|
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor
|
||||||
.ofExisting(new MockPropertySource());
|
.ofExisting(new MockPropertySource());
|
||||||
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
||||||
Arrays.asList(contributor));
|
this.bootstrapRegistry, Arrays.asList(contributor));
|
||||||
ConfigDataEnvironmentContributors withProcessedImports = contributors.withProcessedImports(this.importer,
|
ConfigDataEnvironmentContributors withProcessedImports = contributors.withProcessedImports(this.importer,
|
||||||
this.activationContext);
|
this.activationContext);
|
||||||
assertThat(withProcessedImports).isSameAs(contributors);
|
assertThat(withProcessedImports).isSameAs(contributors);
|
||||||
@ -107,10 +114,11 @@ class ConfigDataEnvironmentContributorsTests {
|
|||||||
MockPropertySource propertySource = new MockPropertySource();
|
MockPropertySource propertySource = new MockPropertySource();
|
||||||
Map<ConfigDataLocation, ConfigData> imported = new LinkedHashMap<>();
|
Map<ConfigDataLocation, ConfigData> imported = new LinkedHashMap<>();
|
||||||
imported.put(new TestConfigDataLocation("a"), new ConfigData(Arrays.asList(propertySource)));
|
imported.put(new TestConfigDataLocation("a"), new ConfigData(Arrays.asList(propertySource)));
|
||||||
given(this.importer.resolveAndLoad(eq(this.activationContext), any(), eq(locations))).willReturn(imported);
|
given(this.importer.resolveAndLoad(eq(this.activationContext), any(), any(), eq(locations)))
|
||||||
|
.willReturn(imported);
|
||||||
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofInitialImport("testimport");
|
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofInitialImport("testimport");
|
||||||
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
||||||
Arrays.asList(contributor));
|
this.bootstrapRegistry, Arrays.asList(contributor));
|
||||||
ConfigDataEnvironmentContributors withProcessedImports = contributors.withProcessedImports(this.importer,
|
ConfigDataEnvironmentContributors withProcessedImports = contributors.withProcessedImports(this.importer,
|
||||||
this.activationContext);
|
this.activationContext);
|
||||||
Iterator<ConfigDataEnvironmentContributor> iterator = withProcessedImports.iterator();
|
Iterator<ConfigDataEnvironmentContributor> iterator = withProcessedImports.iterator();
|
||||||
@ -128,18 +136,18 @@ class ConfigDataEnvironmentContributorsTests {
|
|||||||
initialPropertySource.setProperty("spring.config.import", "secondimport");
|
initialPropertySource.setProperty("spring.config.import", "secondimport");
|
||||||
Map<ConfigDataLocation, ConfigData> initialImported = new LinkedHashMap<>();
|
Map<ConfigDataLocation, ConfigData> initialImported = new LinkedHashMap<>();
|
||||||
initialImported.put(new TestConfigDataLocation("a"), new ConfigData(Arrays.asList(initialPropertySource)));
|
initialImported.put(new TestConfigDataLocation("a"), new ConfigData(Arrays.asList(initialPropertySource)));
|
||||||
given(this.importer.resolveAndLoad(eq(this.activationContext), any(), eq(initialLocations)))
|
given(this.importer.resolveAndLoad(eq(this.activationContext), any(), any(), eq(initialLocations)))
|
||||||
.willReturn(initialImported);
|
.willReturn(initialImported);
|
||||||
List<String> secondLocations = Arrays.asList("secondimport");
|
List<String> secondLocations = Arrays.asList("secondimport");
|
||||||
MockPropertySource secondPropertySource = new MockPropertySource();
|
MockPropertySource secondPropertySource = new MockPropertySource();
|
||||||
Map<ConfigDataLocation, ConfigData> secondImported = new LinkedHashMap<>();
|
Map<ConfigDataLocation, ConfigData> secondImported = new LinkedHashMap<>();
|
||||||
secondImported.put(new TestConfigDataLocation("b"), new ConfigData(Arrays.asList(secondPropertySource)));
|
secondImported.put(new TestConfigDataLocation("b"), new ConfigData(Arrays.asList(secondPropertySource)));
|
||||||
given(this.importer.resolveAndLoad(eq(this.activationContext), any(), eq(secondLocations)))
|
given(this.importer.resolveAndLoad(eq(this.activationContext), any(), any(), eq(secondLocations)))
|
||||||
.willReturn(secondImported);
|
.willReturn(secondImported);
|
||||||
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor
|
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor
|
||||||
.ofInitialImport("initialimport");
|
.ofInitialImport("initialimport");
|
||||||
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
||||||
Arrays.asList(contributor));
|
this.bootstrapRegistry, Arrays.asList(contributor));
|
||||||
ConfigDataEnvironmentContributors withProcessedImports = contributors.withProcessedImports(this.importer,
|
ConfigDataEnvironmentContributors withProcessedImports = contributors.withProcessedImports(this.importer,
|
||||||
this.activationContext);
|
this.activationContext);
|
||||||
Iterator<ConfigDataEnvironmentContributor> iterator = withProcessedImports.iterator();
|
Iterator<ConfigDataEnvironmentContributor> iterator = withProcessedImports.iterator();
|
||||||
@ -161,12 +169,13 @@ class ConfigDataEnvironmentContributorsTests {
|
|||||||
MockPropertySource propertySource = new MockPropertySource();
|
MockPropertySource propertySource = new MockPropertySource();
|
||||||
Map<ConfigDataLocation, ConfigData> imported = new LinkedHashMap<>();
|
Map<ConfigDataLocation, ConfigData> imported = new LinkedHashMap<>();
|
||||||
imported.put(new TestConfigDataLocation("a'"), new ConfigData(Arrays.asList(propertySource)));
|
imported.put(new TestConfigDataLocation("a'"), new ConfigData(Arrays.asList(propertySource)));
|
||||||
given(this.importer.resolveAndLoad(eq(this.activationContext), any(), eq(locations))).willReturn(imported);
|
given(this.importer.resolveAndLoad(eq(this.activationContext), any(), any(), eq(locations)))
|
||||||
|
.willReturn(imported);
|
||||||
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofInitialImport("testimport");
|
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofInitialImport("testimport");
|
||||||
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
||||||
Arrays.asList(existingContributor, contributor));
|
this.bootstrapRegistry, Arrays.asList(existingContributor, contributor));
|
||||||
contributors.withProcessedImports(this.importer, this.activationContext);
|
contributors.withProcessedImports(this.importer, this.activationContext);
|
||||||
verify(this.importer).resolveAndLoad(any(), this.locationResolverContext.capture(), any());
|
verify(this.importer).resolveAndLoad(any(), this.locationResolverContext.capture(), any(), any());
|
||||||
ConfigDataLocationResolverContext context = this.locationResolverContext.getValue();
|
ConfigDataLocationResolverContext context = this.locationResolverContext.getValue();
|
||||||
assertThat(context.getBinder().bind("test", String.class).get()).isEqualTo("springboot");
|
assertThat(context.getBinder().bind("test", String.class).get()).isEqualTo("springboot");
|
||||||
}
|
}
|
||||||
@ -179,31 +188,75 @@ class ConfigDataEnvironmentContributorsTests {
|
|||||||
initialPropertySource.setProperty("spring.config.import", "secondimport");
|
initialPropertySource.setProperty("spring.config.import", "secondimport");
|
||||||
Map<ConfigDataLocation, ConfigData> initialImported = new LinkedHashMap<>();
|
Map<ConfigDataLocation, ConfigData> initialImported = new LinkedHashMap<>();
|
||||||
initialImported.put(new TestConfigDataLocation("a"), new ConfigData(Arrays.asList(initialPropertySource)));
|
initialImported.put(new TestConfigDataLocation("a"), new ConfigData(Arrays.asList(initialPropertySource)));
|
||||||
given(this.importer.resolveAndLoad(eq(this.activationContext), any(), eq(initialLocations)))
|
given(this.importer.resolveAndLoad(eq(this.activationContext), any(), any(), eq(initialLocations)))
|
||||||
.willReturn(initialImported);
|
.willReturn(initialImported);
|
||||||
List<String> secondLocations = Arrays.asList("secondimport");
|
List<String> secondLocations = Arrays.asList("secondimport");
|
||||||
MockPropertySource secondPropertySource = new MockPropertySource();
|
MockPropertySource secondPropertySource = new MockPropertySource();
|
||||||
Map<ConfigDataLocation, ConfigData> secondImported = new LinkedHashMap<>();
|
Map<ConfigDataLocation, ConfigData> secondImported = new LinkedHashMap<>();
|
||||||
secondImported.put(new TestConfigDataLocation("b"), new ConfigData(Arrays.asList(secondPropertySource)));
|
secondImported.put(new TestConfigDataLocation("b"), new ConfigData(Arrays.asList(secondPropertySource)));
|
||||||
given(this.importer.resolveAndLoad(eq(this.activationContext), any(), eq(secondLocations)))
|
given(this.importer.resolveAndLoad(eq(this.activationContext), any(), any(), eq(secondLocations)))
|
||||||
.willReturn(secondImported);
|
.willReturn(secondImported);
|
||||||
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor
|
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor
|
||||||
.ofInitialImport("initialimport");
|
.ofInitialImport("initialimport");
|
||||||
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
||||||
Arrays.asList(contributor));
|
this.bootstrapRegistry, Arrays.asList(contributor));
|
||||||
contributors.withProcessedImports(this.importer, this.activationContext);
|
contributors.withProcessedImports(this.importer, this.activationContext);
|
||||||
verify(this.importer).resolveAndLoad(any(), this.locationResolverContext.capture(), eq(secondLocations));
|
verify(this.importer).resolveAndLoad(any(), this.locationResolverContext.capture(), any(), eq(secondLocations));
|
||||||
ConfigDataLocationResolverContext context = this.locationResolverContext.getValue();
|
ConfigDataLocationResolverContext context = this.locationResolverContext.getValue();
|
||||||
assertThat(context.getParent()).hasToString("a");
|
assertThat(context.getParent()).hasToString("a");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void withProcessedImportsProvidesLocationResolverContextWithAccessToBootstrapRegistry() {
|
||||||
|
MockPropertySource existingPropertySource = new MockPropertySource();
|
||||||
|
existingPropertySource.setProperty("test", "springboot");
|
||||||
|
ConfigDataEnvironmentContributor existingContributor = ConfigDataEnvironmentContributor
|
||||||
|
.ofExisting(existingPropertySource);
|
||||||
|
this.importer = mock(ConfigDataImporter.class);
|
||||||
|
List<String> locations = Arrays.asList("testimport");
|
||||||
|
MockPropertySource propertySource = new MockPropertySource();
|
||||||
|
Map<ConfigDataLocation, ConfigData> imported = new LinkedHashMap<>();
|
||||||
|
imported.put(new TestConfigDataLocation("a'"), new ConfigData(Arrays.asList(propertySource)));
|
||||||
|
given(this.importer.resolveAndLoad(eq(this.activationContext), any(), any(), eq(locations)))
|
||||||
|
.willReturn(imported);
|
||||||
|
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofInitialImport("testimport");
|
||||||
|
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
||||||
|
this.bootstrapRegistry, Arrays.asList(existingContributor, contributor));
|
||||||
|
contributors.withProcessedImports(this.importer, this.activationContext);
|
||||||
|
verify(this.importer).resolveAndLoad(any(), this.locationResolverContext.capture(), any(), any());
|
||||||
|
ConfigDataLocationResolverContext context = this.locationResolverContext.getValue();
|
||||||
|
assertThat(context.getBootstrapRegistry()).isSameAs(this.bootstrapRegistry);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void withProcessedImportsProvidesLoaderContextWithAccessToBootstrapRegistry() {
|
||||||
|
MockPropertySource existingPropertySource = new MockPropertySource();
|
||||||
|
existingPropertySource.setProperty("test", "springboot");
|
||||||
|
ConfigDataEnvironmentContributor existingContributor = ConfigDataEnvironmentContributor
|
||||||
|
.ofExisting(existingPropertySource);
|
||||||
|
this.importer = mock(ConfigDataImporter.class);
|
||||||
|
List<String> locations = Arrays.asList("testimport");
|
||||||
|
MockPropertySource propertySource = new MockPropertySource();
|
||||||
|
Map<ConfigDataLocation, ConfigData> imported = new LinkedHashMap<>();
|
||||||
|
imported.put(new TestConfigDataLocation("a'"), new ConfigData(Arrays.asList(propertySource)));
|
||||||
|
given(this.importer.resolveAndLoad(eq(this.activationContext), any(), any(), eq(locations)))
|
||||||
|
.willReturn(imported);
|
||||||
|
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofInitialImport("testimport");
|
||||||
|
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
||||||
|
this.bootstrapRegistry, Arrays.asList(existingContributor, contributor));
|
||||||
|
contributors.withProcessedImports(this.importer, this.activationContext);
|
||||||
|
verify(this.importer).resolveAndLoad(any(), any(), this.loaderContext.capture(), any());
|
||||||
|
ConfigDataLoaderContext context = this.loaderContext.getValue();
|
||||||
|
assertThat(context.getBootstrapRegistry()).isSameAs(this.bootstrapRegistry);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void getBinderProvidesBinder() {
|
void getBinderProvidesBinder() {
|
||||||
MockPropertySource propertySource = new MockPropertySource();
|
MockPropertySource propertySource = new MockPropertySource();
|
||||||
propertySource.setProperty("test", "springboot");
|
propertySource.setProperty("test", "springboot");
|
||||||
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofExisting(propertySource);
|
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofExisting(propertySource);
|
||||||
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
||||||
Arrays.asList(contributor));
|
this.bootstrapRegistry, Arrays.asList(contributor));
|
||||||
Binder binder = contributors.getBinder(this.activationContext);
|
Binder binder = contributors.getBinder(this.activationContext);
|
||||||
assertThat(binder.bind("test", String.class).get()).isEqualTo("springboot");
|
assertThat(binder.bind("test", String.class).get()).isEqualTo("springboot");
|
||||||
}
|
}
|
||||||
@ -220,7 +273,7 @@ class ConfigDataEnvironmentContributorsTests {
|
|||||||
ConfigDataEnvironmentContributor secondContributor = ConfigDataEnvironmentContributor.ofImported(null,
|
ConfigDataEnvironmentContributor secondContributor = ConfigDataEnvironmentContributor.ofImported(null,
|
||||||
configData, 1, this.activationContext);
|
configData, 1, this.activationContext);
|
||||||
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
||||||
Arrays.asList(firstContributor, secondContributor));
|
this.bootstrapRegistry, Arrays.asList(firstContributor, secondContributor));
|
||||||
Binder binder = contributors.getBinder(this.activationContext);
|
Binder binder = contributors.getBinder(this.activationContext);
|
||||||
assertThat(binder.bind("test", String.class).get()).isEqualTo("one");
|
assertThat(binder.bind("test", String.class).get()).isEqualTo("one");
|
||||||
}
|
}
|
||||||
@ -238,7 +291,7 @@ class ConfigDataEnvironmentContributorsTests {
|
|||||||
ConfigDataEnvironmentContributor secondContributor = ConfigDataEnvironmentContributor.ofImported(null,
|
ConfigDataEnvironmentContributor secondContributor = ConfigDataEnvironmentContributor.ofImported(null,
|
||||||
configData, 1, this.activationContext);
|
configData, 1, this.activationContext);
|
||||||
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
||||||
Arrays.asList(firstContributor, secondContributor));
|
this.bootstrapRegistry, Arrays.asList(firstContributor, secondContributor));
|
||||||
Binder binder = contributors.getBinder(this.activationContext);
|
Binder binder = contributors.getBinder(this.activationContext);
|
||||||
assertThat(binder.bind("test", String.class).get()).isEqualTo("two");
|
assertThat(binder.bind("test", String.class).get()).isEqualTo("two");
|
||||||
}
|
}
|
||||||
@ -250,7 +303,7 @@ class ConfigDataEnvironmentContributorsTests {
|
|||||||
propertySource.setProperty("other", "springboot");
|
propertySource.setProperty("other", "springboot");
|
||||||
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofExisting(propertySource);
|
ConfigDataEnvironmentContributor contributor = ConfigDataEnvironmentContributor.ofExisting(propertySource);
|
||||||
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
||||||
Arrays.asList(contributor));
|
this.bootstrapRegistry, Arrays.asList(contributor));
|
||||||
Binder binder = contributors.getBinder(this.activationContext);
|
Binder binder = contributors.getBinder(this.activationContext);
|
||||||
assertThat(binder.bind("test", String.class).get()).isEqualTo("springboot");
|
assertThat(binder.bind("test", String.class).get()).isEqualTo("springboot");
|
||||||
}
|
}
|
||||||
@ -269,7 +322,7 @@ class ConfigDataEnvironmentContributorsTests {
|
|||||||
ConfigDataEnvironmentContributor secondContributor = ConfigDataEnvironmentContributor.ofImported(null,
|
ConfigDataEnvironmentContributor secondContributor = ConfigDataEnvironmentContributor.ofImported(null,
|
||||||
configData, 1, this.activationContext);
|
configData, 1, this.activationContext);
|
||||||
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
||||||
Arrays.asList(firstContributor, secondContributor));
|
this.bootstrapRegistry, Arrays.asList(firstContributor, secondContributor));
|
||||||
Binder binder = contributors.getBinder(this.activationContext);
|
Binder binder = contributors.getBinder(this.activationContext);
|
||||||
assertThat(binder.bind("test", String.class).get()).isEqualTo("two");
|
assertThat(binder.bind("test", String.class).get()).isEqualTo("two");
|
||||||
}
|
}
|
||||||
@ -287,7 +340,7 @@ class ConfigDataEnvironmentContributorsTests {
|
|||||||
ConfigDataEnvironmentContributor secondContributor = ConfigDataEnvironmentContributor.ofImported(null,
|
ConfigDataEnvironmentContributor secondContributor = ConfigDataEnvironmentContributor.ofImported(null,
|
||||||
configData, 1, this.activationContext);
|
configData, 1, this.activationContext);
|
||||||
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
||||||
Arrays.asList(firstContributor, secondContributor));
|
this.bootstrapRegistry, Arrays.asList(firstContributor, secondContributor));
|
||||||
Binder binder = contributors.getBinder(this.activationContext, BinderOption.FAIL_ON_BIND_TO_INACTIVE_SOURCE);
|
Binder binder = contributors.getBinder(this.activationContext, BinderOption.FAIL_ON_BIND_TO_INACTIVE_SOURCE);
|
||||||
assertThatExceptionOfType(BindException.class).isThrownBy(() -> binder.bind("test", String.class))
|
assertThatExceptionOfType(BindException.class).isThrownBy(() -> binder.bind("test", String.class))
|
||||||
.satisfies((ex) -> assertThat(ex.getCause()).isInstanceOf(InactiveConfigDataAccessException.class));
|
.satisfies((ex) -> assertThat(ex.getCause()).isInstanceOf(InactiveConfigDataAccessException.class));
|
||||||
@ -306,7 +359,7 @@ class ConfigDataEnvironmentContributorsTests {
|
|||||||
ConfigDataEnvironmentContributor secondContributor = ConfigDataEnvironmentContributor.ofImported(null,
|
ConfigDataEnvironmentContributor secondContributor = ConfigDataEnvironmentContributor.ofImported(null,
|
||||||
configData, 1, this.activationContext);
|
configData, 1, this.activationContext);
|
||||||
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
||||||
Arrays.asList(firstContributor, secondContributor));
|
this.bootstrapRegistry, Arrays.asList(firstContributor, secondContributor));
|
||||||
Binder binder = contributors.getBinder(this.activationContext, BinderOption.FAIL_ON_BIND_TO_INACTIVE_SOURCE);
|
Binder binder = contributors.getBinder(this.activationContext, BinderOption.FAIL_ON_BIND_TO_INACTIVE_SOURCE);
|
||||||
assertThatExceptionOfType(BindException.class).isThrownBy(() -> binder.bind("test", String.class))
|
assertThatExceptionOfType(BindException.class).isThrownBy(() -> binder.bind("test", String.class))
|
||||||
.satisfies((ex) -> assertThat(ex.getCause()).isInstanceOf(InactiveConfigDataAccessException.class));
|
.satisfies((ex) -> assertThat(ex.getCause()).isInstanceOf(InactiveConfigDataAccessException.class));
|
||||||
@ -326,7 +379,7 @@ class ConfigDataEnvironmentContributorsTests {
|
|||||||
ConfigDataEnvironmentContributor secondContributor = ConfigDataEnvironmentContributor.ofImported(null,
|
ConfigDataEnvironmentContributor secondContributor = ConfigDataEnvironmentContributor.ofImported(null,
|
||||||
configData, 1, this.activationContext);
|
configData, 1, this.activationContext);
|
||||||
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
ConfigDataEnvironmentContributors contributors = new ConfigDataEnvironmentContributors(this.logFactory,
|
||||||
Arrays.asList(firstContributor, secondContributor));
|
this.bootstrapRegistry, Arrays.asList(firstContributor, secondContributor));
|
||||||
Binder binder = contributors.getBinder(this.activationContext, BinderOption.FAIL_ON_BIND_TO_INACTIVE_SOURCE);
|
Binder binder = contributors.getBinder(this.activationContext, BinderOption.FAIL_ON_BIND_TO_INACTIVE_SOURCE);
|
||||||
assertThatExceptionOfType(BindException.class).isThrownBy(() -> binder.bind("test", String.class))
|
assertThatExceptionOfType(BindException.class).isThrownBy(() -> binder.bind("test", String.class))
|
||||||
.satisfies((ex) -> assertThat(ex.getCause()).isInstanceOf(InactiveConfigDataAccessException.class));
|
.satisfies((ex) -> assertThat(ex.getCause()).isInstanceOf(InactiveConfigDataAccessException.class));
|
||||||
|
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* 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.context.config;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.WebApplicationType;
|
||||||
|
import org.springframework.boot.context.config.TestConfigDataBootstrap.LoaderHelper;
|
||||||
|
import org.springframework.boot.env.BootstrapRegistry;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests for {@link ConfigDataEnvironmentPostProcessor} when used with a
|
||||||
|
* {@link BootstrapRegistry}.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
class ConfigDataEnvironmentPostProcessorBootstrapRegistryIntegrationTests {
|
||||||
|
|
||||||
|
private SpringApplication application;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setup() {
|
||||||
|
this.application = new SpringApplication(Config.class);
|
||||||
|
this.application.setWebApplicationType(WebApplicationType.NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void bootstrapsApplicationContext() {
|
||||||
|
try (ConfigurableApplicationContext context = this.application
|
||||||
|
.run("--spring.config.import=classpath:application-bootstrap-registry-integration-tests.properties")) {
|
||||||
|
LoaderHelper bean = context.getBean(TestConfigDataBootstrap.LoaderHelper.class);
|
||||||
|
assertThat(bean).isNotNull();
|
||||||
|
assertThat(bean.getLocation().getResolverHelper().getLocation()).isEqualTo("testbootstrap:test");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
static class Config {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -28,6 +28,7 @@ import org.mockito.Spy;
|
|||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.env.DefaultBootstrapRegisty;
|
||||||
import org.springframework.core.env.StandardEnvironment;
|
import org.springframework.core.env.StandardEnvironment;
|
||||||
import org.springframework.core.io.DefaultResourceLoader;
|
import org.springframework.core.io.DefaultResourceLoader;
|
||||||
import org.springframework.core.io.ResourceLoader;
|
import org.springframework.core.io.ResourceLoader;
|
||||||
@ -58,7 +59,8 @@ class ConfigDataEnvironmentPostProcessorTests {
|
|||||||
private ConfigDataEnvironment configDataEnvironment;
|
private ConfigDataEnvironment configDataEnvironment;
|
||||||
|
|
||||||
@Spy
|
@Spy
|
||||||
private ConfigDataEnvironmentPostProcessor postProcessor = new ConfigDataEnvironmentPostProcessor(Supplier::get);
|
private ConfigDataEnvironmentPostProcessor postProcessor = new ConfigDataEnvironmentPostProcessor(Supplier::get,
|
||||||
|
new DefaultBootstrapRegisty());
|
||||||
|
|
||||||
@Captor
|
@Captor
|
||||||
private ArgumentCaptor<Set<String>> additionalProfilesCaptor;
|
private ArgumentCaptor<Set<String>> additionalProfilesCaptor;
|
||||||
@ -117,7 +119,7 @@ class ConfigDataEnvironmentPostProcessorTests {
|
|||||||
@Test
|
@Test
|
||||||
void applyToAppliesPostProcessing() {
|
void applyToAppliesPostProcessing() {
|
||||||
int before = this.environment.getPropertySources().size();
|
int before = this.environment.getPropertySources().size();
|
||||||
ConfigDataEnvironmentPostProcessor.applyTo(this.environment, null, "dev");
|
ConfigDataEnvironmentPostProcessor.applyTo(this.environment, null, null, "dev");
|
||||||
assertThat(this.environment.getPropertySources().size()).isGreaterThan(before);
|
assertThat(this.environment.getPropertySources().size()).isGreaterThan(before);
|
||||||
assertThat(this.environment.getActiveProfiles()).containsExactly("dev");
|
assertThat(this.environment.getActiveProfiles()).containsExactly("dev");
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,8 @@ import org.junit.jupiter.api.TestInfo;
|
|||||||
import org.springframework.boot.context.config.ConfigDataEnvironmentContributor.ImportPhase;
|
import org.springframework.boot.context.config.ConfigDataEnvironmentContributor.ImportPhase;
|
||||||
import org.springframework.boot.context.config.ConfigDataEnvironmentContributor.Kind;
|
import org.springframework.boot.context.config.ConfigDataEnvironmentContributor.Kind;
|
||||||
import org.springframework.boot.context.properties.bind.Binder;
|
import org.springframework.boot.context.properties.bind.Binder;
|
||||||
|
import org.springframework.boot.env.BootstrapRegistry;
|
||||||
|
import org.springframework.boot.env.DefaultBootstrapRegisty;
|
||||||
import org.springframework.boot.logging.DeferredLogFactory;
|
import org.springframework.boot.logging.DeferredLogFactory;
|
||||||
import org.springframework.core.env.ConfigurableEnvironment;
|
import org.springframework.core.env.ConfigurableEnvironment;
|
||||||
import org.springframework.core.env.PropertySource;
|
import org.springframework.core.env.PropertySource;
|
||||||
@ -50,6 +52,8 @@ class ConfigDataEnvironmentTests {
|
|||||||
|
|
||||||
private DeferredLogFactory logFactory = Supplier::get;
|
private DeferredLogFactory logFactory = Supplier::get;
|
||||||
|
|
||||||
|
private BootstrapRegistry bootstrapRegistry = new DefaultBootstrapRegisty();
|
||||||
|
|
||||||
private MockEnvironment environment = new MockEnvironment();
|
private MockEnvironment environment = new MockEnvironment();
|
||||||
|
|
||||||
private ResourceLoader resourceLoader = new DefaultResourceLoader();
|
private ResourceLoader resourceLoader = new DefaultResourceLoader();
|
||||||
@ -60,15 +64,15 @@ class ConfigDataEnvironmentTests {
|
|||||||
void createWhenUseLegacyPropertyInEnvironmentThrowsException() {
|
void createWhenUseLegacyPropertyInEnvironmentThrowsException() {
|
||||||
this.environment.setProperty("spring.config.use-legacy-processing", "true");
|
this.environment.setProperty("spring.config.use-legacy-processing", "true");
|
||||||
assertThatExceptionOfType(UseLegacyConfigProcessingException.class)
|
assertThatExceptionOfType(UseLegacyConfigProcessingException.class)
|
||||||
.isThrownBy(() -> new ConfigDataEnvironment(this.logFactory, this.environment, this.resourceLoader,
|
.isThrownBy(() -> new ConfigDataEnvironment(this.logFactory, this.bootstrapRegistry, this.environment,
|
||||||
this.additionalProfiles));
|
this.resourceLoader, this.additionalProfiles));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void createExposesEnvironmentBinderToConfigDataLocationResolvers() {
|
void createExposesEnvironmentBinderToConfigDataLocationResolvers() {
|
||||||
this.environment.setProperty("spring", "boot");
|
this.environment.setProperty("spring", "boot");
|
||||||
TestConfigDataEnvironment configDataEnvironment = new TestConfigDataEnvironment(this.logFactory,
|
TestConfigDataEnvironment configDataEnvironment = new TestConfigDataEnvironment(this.logFactory,
|
||||||
this.environment, this.resourceLoader, this.additionalProfiles);
|
this.bootstrapRegistry, this.environment, this.resourceLoader, this.additionalProfiles);
|
||||||
assertThat(configDataEnvironment.getConfigDataLocationResolversBinder().bind("spring", String.class).get())
|
assertThat(configDataEnvironment.getConfigDataLocationResolversBinder().bind("spring", String.class).get())
|
||||||
.isEqualTo("boot");
|
.isEqualTo("boot");
|
||||||
}
|
}
|
||||||
@ -81,8 +85,8 @@ class ConfigDataEnvironmentTests {
|
|||||||
this.environment.getPropertySources().addLast(propertySource1);
|
this.environment.getPropertySources().addLast(propertySource1);
|
||||||
this.environment.getPropertySources().addLast(propertySource2);
|
this.environment.getPropertySources().addLast(propertySource2);
|
||||||
this.environment.getPropertySources().addLast(propertySource3);
|
this.environment.getPropertySources().addLast(propertySource3);
|
||||||
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.environment,
|
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapRegistry,
|
||||||
this.resourceLoader, this.additionalProfiles);
|
this.environment, this.resourceLoader, this.additionalProfiles);
|
||||||
List<ConfigDataEnvironmentContributor> children = configDataEnvironment.getContributors().getRoot()
|
List<ConfigDataEnvironmentContributor> children = configDataEnvironment.getContributors().getRoot()
|
||||||
.getChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION);
|
.getChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION);
|
||||||
Object[] wrapped = children.stream().filter((child) -> child.getKind() == Kind.EXISTING)
|
Object[] wrapped = children.stream().filter((child) -> child.getKind() == Kind.EXISTING)
|
||||||
@ -100,8 +104,8 @@ class ConfigDataEnvironmentTests {
|
|||||||
this.environment.getPropertySources().addLast(defaultPropertySource);
|
this.environment.getPropertySources().addLast(defaultPropertySource);
|
||||||
this.environment.getPropertySources().addLast(propertySource1);
|
this.environment.getPropertySources().addLast(propertySource1);
|
||||||
this.environment.getPropertySources().addLast(propertySource2);
|
this.environment.getPropertySources().addLast(propertySource2);
|
||||||
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.environment,
|
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapRegistry,
|
||||||
this.resourceLoader, this.additionalProfiles);
|
this.environment, this.resourceLoader, this.additionalProfiles);
|
||||||
List<ConfigDataEnvironmentContributor> children = configDataEnvironment.getContributors().getRoot()
|
List<ConfigDataEnvironmentContributor> children = configDataEnvironment.getContributors().getRoot()
|
||||||
.getChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION);
|
.getChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION);
|
||||||
Object[] wrapped = children.stream().filter((child) -> child.getKind() == Kind.EXISTING)
|
Object[] wrapped = children.stream().filter((child) -> child.getKind() == Kind.EXISTING)
|
||||||
@ -116,8 +120,8 @@ class ConfigDataEnvironmentTests {
|
|||||||
this.environment.setProperty("spring.config.location", "l1,l2");
|
this.environment.setProperty("spring.config.location", "l1,l2");
|
||||||
this.environment.setProperty("spring.config.additional-location", "a1,a2");
|
this.environment.setProperty("spring.config.additional-location", "a1,a2");
|
||||||
this.environment.setProperty("spring.config.import", "i1,i2");
|
this.environment.setProperty("spring.config.import", "i1,i2");
|
||||||
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.environment,
|
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapRegistry,
|
||||||
this.resourceLoader, this.additionalProfiles);
|
this.environment, this.resourceLoader, this.additionalProfiles);
|
||||||
List<ConfigDataEnvironmentContributor> children = configDataEnvironment.getContributors().getRoot()
|
List<ConfigDataEnvironmentContributor> children = configDataEnvironment.getContributors().getRoot()
|
||||||
.getChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION);
|
.getChildren(ImportPhase.BEFORE_PROFILE_ACTIVATION);
|
||||||
Object[] imports = children.stream().filter((child) -> child.getKind() == Kind.INITIAL_IMPORT)
|
Object[] imports = children.stream().filter((child) -> child.getKind() == Kind.INITIAL_IMPORT)
|
||||||
@ -128,8 +132,8 @@ class ConfigDataEnvironmentTests {
|
|||||||
@Test
|
@Test
|
||||||
void processAndApplyAddsImportedSourceToEnvironment(TestInfo info) {
|
void processAndApplyAddsImportedSourceToEnvironment(TestInfo info) {
|
||||||
this.environment.setProperty("spring.config.location", getConfigLocation(info));
|
this.environment.setProperty("spring.config.location", getConfigLocation(info));
|
||||||
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.environment,
|
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapRegistry,
|
||||||
this.resourceLoader, this.additionalProfiles);
|
this.environment, this.resourceLoader, this.additionalProfiles);
|
||||||
configDataEnvironment.processAndApply();
|
configDataEnvironment.processAndApply();
|
||||||
assertThat(this.environment.getProperty("spring")).isEqualTo("boot");
|
assertThat(this.environment.getProperty("spring")).isEqualTo("boot");
|
||||||
}
|
}
|
||||||
@ -137,8 +141,8 @@ class ConfigDataEnvironmentTests {
|
|||||||
@Test
|
@Test
|
||||||
void processAndApplyOnlyAddsActiveContributors(TestInfo info) {
|
void processAndApplyOnlyAddsActiveContributors(TestInfo info) {
|
||||||
this.environment.setProperty("spring.config.location", getConfigLocation(info));
|
this.environment.setProperty("spring.config.location", getConfigLocation(info));
|
||||||
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.environment,
|
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapRegistry,
|
||||||
this.resourceLoader, this.additionalProfiles);
|
this.environment, this.resourceLoader, this.additionalProfiles);
|
||||||
configDataEnvironment.processAndApply();
|
configDataEnvironment.processAndApply();
|
||||||
assertThat(this.environment.getProperty("spring")).isEqualTo("boot");
|
assertThat(this.environment.getProperty("spring")).isEqualTo("boot");
|
||||||
assertThat(this.environment.getProperty("other")).isNull();
|
assertThat(this.environment.getProperty("other")).isNull();
|
||||||
@ -149,8 +153,8 @@ class ConfigDataEnvironmentTests {
|
|||||||
MockPropertySource defaultPropertySource = new MockPropertySource("defaultProperties");
|
MockPropertySource defaultPropertySource = new MockPropertySource("defaultProperties");
|
||||||
this.environment.getPropertySources().addFirst(defaultPropertySource);
|
this.environment.getPropertySources().addFirst(defaultPropertySource);
|
||||||
this.environment.setProperty("spring.config.location", getConfigLocation(info));
|
this.environment.setProperty("spring.config.location", getConfigLocation(info));
|
||||||
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.environment,
|
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapRegistry,
|
||||||
this.resourceLoader, this.additionalProfiles);
|
this.environment, this.resourceLoader, this.additionalProfiles);
|
||||||
configDataEnvironment.processAndApply();
|
configDataEnvironment.processAndApply();
|
||||||
List<PropertySource<?>> sources = this.environment.getPropertySources().stream().collect(Collectors.toList());
|
List<PropertySource<?>> sources = this.environment.getPropertySources().stream().collect(Collectors.toList());
|
||||||
assertThat(sources.get(sources.size() - 1)).isSameAs(defaultPropertySource);
|
assertThat(sources.get(sources.size() - 1)).isSameAs(defaultPropertySource);
|
||||||
@ -159,8 +163,8 @@ class ConfigDataEnvironmentTests {
|
|||||||
@Test
|
@Test
|
||||||
void processAndApplySetsDefaultProfiles(TestInfo info) {
|
void processAndApplySetsDefaultProfiles(TestInfo info) {
|
||||||
this.environment.setProperty("spring.config.location", getConfigLocation(info));
|
this.environment.setProperty("spring.config.location", getConfigLocation(info));
|
||||||
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.environment,
|
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapRegistry,
|
||||||
this.resourceLoader, this.additionalProfiles);
|
this.environment, this.resourceLoader, this.additionalProfiles);
|
||||||
configDataEnvironment.processAndApply();
|
configDataEnvironment.processAndApply();
|
||||||
assertThat(this.environment.getDefaultProfiles()).containsExactly("one", "two", "three");
|
assertThat(this.environment.getDefaultProfiles()).containsExactly("one", "two", "three");
|
||||||
}
|
}
|
||||||
@ -168,8 +172,8 @@ class ConfigDataEnvironmentTests {
|
|||||||
@Test
|
@Test
|
||||||
void processAndApplySetsActiveProfiles(TestInfo info) {
|
void processAndApplySetsActiveProfiles(TestInfo info) {
|
||||||
this.environment.setProperty("spring.config.location", getConfigLocation(info));
|
this.environment.setProperty("spring.config.location", getConfigLocation(info));
|
||||||
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.environment,
|
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapRegistry,
|
||||||
this.resourceLoader, this.additionalProfiles);
|
this.environment, this.resourceLoader, this.additionalProfiles);
|
||||||
configDataEnvironment.processAndApply();
|
configDataEnvironment.processAndApply();
|
||||||
assertThat(this.environment.getActiveProfiles()).containsExactly("one", "two", "three");
|
assertThat(this.environment.getActiveProfiles()).containsExactly("one", "two", "three");
|
||||||
}
|
}
|
||||||
@ -177,8 +181,8 @@ class ConfigDataEnvironmentTests {
|
|||||||
@Test
|
@Test
|
||||||
void processAndApplySetsActiveProfilesAndProfileGroups(TestInfo info) {
|
void processAndApplySetsActiveProfilesAndProfileGroups(TestInfo info) {
|
||||||
this.environment.setProperty("spring.config.location", getConfigLocation(info));
|
this.environment.setProperty("spring.config.location", getConfigLocation(info));
|
||||||
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.environment,
|
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapRegistry,
|
||||||
this.resourceLoader, this.additionalProfiles);
|
this.environment, this.resourceLoader, this.additionalProfiles);
|
||||||
configDataEnvironment.processAndApply();
|
configDataEnvironment.processAndApply();
|
||||||
assertThat(this.environment.getActiveProfiles()).containsExactly("one", "four", "five", "two", "three");
|
assertThat(this.environment.getActiveProfiles()).containsExactly("one", "four", "five", "two", "three");
|
||||||
}
|
}
|
||||||
@ -187,8 +191,8 @@ class ConfigDataEnvironmentTests {
|
|||||||
@Disabled("Disabled until spring.profiles suppport is dropped")
|
@Disabled("Disabled until spring.profiles suppport is dropped")
|
||||||
void processAndApplyWhenHasInvalidPropertyThrowsException() {
|
void processAndApplyWhenHasInvalidPropertyThrowsException() {
|
||||||
this.environment.setProperty("spring.profile", "a");
|
this.environment.setProperty("spring.profile", "a");
|
||||||
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.environment,
|
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapRegistry,
|
||||||
this.resourceLoader, this.additionalProfiles);
|
this.environment, this.resourceLoader, this.additionalProfiles);
|
||||||
assertThatExceptionOfType(InvalidConfigDataPropertyException.class)
|
assertThatExceptionOfType(InvalidConfigDataPropertyException.class)
|
||||||
.isThrownBy(() -> configDataEnvironment.processAndApply());
|
.isThrownBy(() -> configDataEnvironment.processAndApply());
|
||||||
}
|
}
|
||||||
@ -202,9 +206,10 @@ class ConfigDataEnvironmentTests {
|
|||||||
|
|
||||||
private Binder configDataLocationResolversBinder;
|
private Binder configDataLocationResolversBinder;
|
||||||
|
|
||||||
TestConfigDataEnvironment(DeferredLogFactory logFactory, ConfigurableEnvironment environment,
|
TestConfigDataEnvironment(DeferredLogFactory logFactory, BootstrapRegistry bootstrapRegistry,
|
||||||
ResourceLoader resourceLoader, Collection<String> additionalProfiles) {
|
ConfigurableEnvironment environment, ResourceLoader resourceLoader,
|
||||||
super(logFactory, environment, resourceLoader, additionalProfiles);
|
Collection<String> additionalProfiles) {
|
||||||
|
super(logFactory, bootstrapRegistry, environment, resourceLoader, additionalProfiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -54,6 +54,9 @@ class ConfigDataImporterTests {
|
|||||||
@Mock
|
@Mock
|
||||||
private ConfigDataLocationResolverContext locationResolverContext;
|
private ConfigDataLocationResolverContext locationResolverContext;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private ConfigDataLoaderContext loaderContext;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private ConfigDataActivationContext activationContext;
|
private ConfigDataActivationContext activationContext;
|
||||||
|
|
||||||
@ -75,11 +78,12 @@ class ConfigDataImporterTests {
|
|||||||
ConfigData configData2 = new ConfigData(Collections.singleton(new MockPropertySource()));
|
ConfigData configData2 = new ConfigData(Collections.singleton(new MockPropertySource()));
|
||||||
given(this.resolvers.resolveAll(this.locationResolverContext, locations, this.profiles))
|
given(this.resolvers.resolveAll(this.locationResolverContext, locations, this.profiles))
|
||||||
.willReturn(resolvedLocations);
|
.willReturn(resolvedLocations);
|
||||||
given(this.loaders.load(resolvedLocation1)).willReturn(configData1);
|
given(this.loaders.load(this.loaderContext, resolvedLocation1)).willReturn(configData1);
|
||||||
given(this.loaders.load(resolvedLocation2)).willReturn(configData2);
|
given(this.loaders.load(this.loaderContext, resolvedLocation2)).willReturn(configData2);
|
||||||
ConfigDataImporter importer = new ConfigDataImporter(this.resolvers, this.loaders);
|
ConfigDataImporter importer = new ConfigDataImporter(this.resolvers, this.loaders);
|
||||||
Collection<ConfigData> loaded = importer
|
Collection<ConfigData> loaded = importer
|
||||||
.resolveAndLoad(this.activationContext, this.locationResolverContext, locations).values();
|
.resolveAndLoad(this.activationContext, this.locationResolverContext, this.loaderContext, locations)
|
||||||
|
.values();
|
||||||
assertThat(loaded).containsExactly(configData2, configData1);
|
assertThat(loaded).containsExactly(configData2, configData1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,14 +103,14 @@ class ConfigDataImporterTests {
|
|||||||
.willReturn(resolvedLocations1and2);
|
.willReturn(resolvedLocations1and2);
|
||||||
given(this.resolvers.resolveAll(this.locationResolverContext, locations2and3, this.profiles))
|
given(this.resolvers.resolveAll(this.locationResolverContext, locations2and3, this.profiles))
|
||||||
.willReturn(resolvedLocations2and3);
|
.willReturn(resolvedLocations2and3);
|
||||||
given(this.loaders.load(resolvedLocation1)).willReturn(configData1);
|
given(this.loaders.load(this.loaderContext, resolvedLocation1)).willReturn(configData1);
|
||||||
given(this.loaders.load(resolvedLocation2)).willReturn(configData2);
|
given(this.loaders.load(this.loaderContext, resolvedLocation2)).willReturn(configData2);
|
||||||
given(this.loaders.load(resolvedLocation3)).willReturn(configData3);
|
given(this.loaders.load(this.loaderContext, resolvedLocation3)).willReturn(configData3);
|
||||||
ConfigDataImporter importer = new ConfigDataImporter(this.resolvers, this.loaders);
|
ConfigDataImporter importer = new ConfigDataImporter(this.resolvers, this.loaders);
|
||||||
Collection<ConfigData> loaded1and2 = importer
|
Collection<ConfigData> loaded1and2 = importer.resolveAndLoad(this.activationContext,
|
||||||
.resolveAndLoad(this.activationContext, this.locationResolverContext, locations1and2).values();
|
this.locationResolverContext, this.loaderContext, locations1and2).values();
|
||||||
Collection<ConfigData> loaded2and3 = importer
|
Collection<ConfigData> loaded2and3 = importer.resolveAndLoad(this.activationContext,
|
||||||
.resolveAndLoad(this.activationContext, this.locationResolverContext, locations2and3).values();
|
this.locationResolverContext, this.loaderContext, locations2and3).values();
|
||||||
assertThat(loaded1and2).containsExactly(configData2, configData1);
|
assertThat(loaded1and2).containsExactly(configData2, configData1);
|
||||||
assertThat(loaded2and3).containsExactly(configData3);
|
assertThat(loaded2and3).containsExactly(configData3);
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import java.io.IOException;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link ConfigDataLoader}.
|
* Tests for {@link ConfigDataLoader}.
|
||||||
@ -32,15 +33,17 @@ class ConfigDataLoaderTests {
|
|||||||
|
|
||||||
private TestConfigDataLoader loader = new TestConfigDataLoader();
|
private TestConfigDataLoader loader = new TestConfigDataLoader();
|
||||||
|
|
||||||
|
private ConfigDataLoaderContext context = mock(ConfigDataLoaderContext.class);
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void isLoadableAlwaysReturnsTrue() {
|
void isLoadableAlwaysReturnsTrue() {
|
||||||
assertThat(this.loader.isLoadable(new TestConfigDataLocation())).isTrue();
|
assertThat(this.loader.isLoadable(this.context, new TestConfigDataLocation())).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
static class TestConfigDataLoader implements ConfigDataLoader<TestConfigDataLocation> {
|
static class TestConfigDataLoader implements ConfigDataLoader<TestConfigDataLocation> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConfigData load(TestConfigDataLocation location) throws IOException {
|
public ConfigData load(ConfigDataLoaderContext context, TestConfigDataLocation location) throws IOException {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ import org.springframework.mock.env.MockPropertySource;
|
|||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link ConfigDataLoaders}.
|
* Tests for {@link ConfigDataLoaders}.
|
||||||
@ -41,6 +42,8 @@ class ConfigDataLoadersTests {
|
|||||||
|
|
||||||
private DeferredLogFactory logFactory = Supplier::get;
|
private DeferredLogFactory logFactory = Supplier::get;
|
||||||
|
|
||||||
|
private ConfigDataLoaderContext context = mock(ConfigDataLoaderContext.class);
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void createWhenLoaderHasLogParameterInjectsLog() {
|
void createWhenLoaderHasLogParameterInjectsLog() {
|
||||||
new ConfigDataLoaders(this.logFactory, Arrays.asList(LoggingConfigDataLoader.class.getName()));
|
new ConfigDataLoaders(this.logFactory, Arrays.asList(LoggingConfigDataLoader.class.getName()));
|
||||||
@ -51,7 +54,7 @@ class ConfigDataLoadersTests {
|
|||||||
TestConfigDataLocation location = new TestConfigDataLocation("test");
|
TestConfigDataLocation location = new TestConfigDataLocation("test");
|
||||||
ConfigDataLoaders loaders = new ConfigDataLoaders(this.logFactory,
|
ConfigDataLoaders loaders = new ConfigDataLoaders(this.logFactory,
|
||||||
Arrays.asList(TestConfigDataLoader.class.getName()));
|
Arrays.asList(TestConfigDataLoader.class.getName()));
|
||||||
ConfigData loaded = loaders.load(location);
|
ConfigData loaded = loaders.load(this.context, location);
|
||||||
assertThat(getLoader(loaded)).isInstanceOf(TestConfigDataLoader.class);
|
assertThat(getLoader(loaded)).isInstanceOf(TestConfigDataLoader.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,7 +63,7 @@ class ConfigDataLoadersTests {
|
|||||||
TestConfigDataLocation location = new TestConfigDataLocation("test");
|
TestConfigDataLocation location = new TestConfigDataLocation("test");
|
||||||
ConfigDataLoaders loaders = new ConfigDataLoaders(this.logFactory,
|
ConfigDataLoaders loaders = new ConfigDataLoaders(this.logFactory,
|
||||||
Arrays.asList(LoggingConfigDataLoader.class.getName(), TestConfigDataLoader.class.getName()));
|
Arrays.asList(LoggingConfigDataLoader.class.getName(), TestConfigDataLoader.class.getName()));
|
||||||
assertThatIllegalStateException().isThrownBy(() -> loaders.load(location))
|
assertThatIllegalStateException().isThrownBy(() -> loaders.load(this.context, location))
|
||||||
.withMessageContaining("Multiple loaders found for location test");
|
.withMessageContaining("Multiple loaders found for location test");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,7 +72,7 @@ class ConfigDataLoadersTests {
|
|||||||
TestConfigDataLocation location = new TestConfigDataLocation("test");
|
TestConfigDataLocation location = new TestConfigDataLocation("test");
|
||||||
ConfigDataLoaders loaders = new ConfigDataLoaders(this.logFactory,
|
ConfigDataLoaders loaders = new ConfigDataLoaders(this.logFactory,
|
||||||
Arrays.asList(NonLoadableConfigDataLoader.class.getName()));
|
Arrays.asList(NonLoadableConfigDataLoader.class.getName()));
|
||||||
assertThatIllegalStateException().isThrownBy(() -> loaders.load(location))
|
assertThatIllegalStateException().isThrownBy(() -> loaders.load(this.context, location))
|
||||||
.withMessage("No loader found for location 'test'");
|
.withMessage("No loader found for location 'test'");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +81,7 @@ class ConfigDataLoadersTests {
|
|||||||
TestConfigDataLocation location = new TestConfigDataLocation("test");
|
TestConfigDataLocation location = new TestConfigDataLocation("test");
|
||||||
ConfigDataLoaders loaders = new ConfigDataLoaders(this.logFactory,
|
ConfigDataLoaders loaders = new ConfigDataLoaders(this.logFactory,
|
||||||
Arrays.asList(OtherConfigDataLoader.class.getName(), SpecificConfigDataLoader.class.getName()));
|
Arrays.asList(OtherConfigDataLoader.class.getName(), SpecificConfigDataLoader.class.getName()));
|
||||||
ConfigData loaded = loaders.load(location);
|
ConfigData loaded = loaders.load(this.context, location);
|
||||||
assertThat(getLoader(loaded)).isInstanceOf(SpecificConfigDataLoader.class);
|
assertThat(getLoader(loaded)).isInstanceOf(SpecificConfigDataLoader.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,7 +124,7 @@ class ConfigDataLoadersTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConfigData load(ConfigDataLocation location) throws IOException {
|
public ConfigData load(ConfigDataLoaderContext context, ConfigDataLocation location) throws IOException {
|
||||||
throw new AssertionError("Unexpected call");
|
throw new AssertionError("Unexpected call");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +133,7 @@ class ConfigDataLoadersTests {
|
|||||||
static class TestConfigDataLoader implements ConfigDataLoader<ConfigDataLocation> {
|
static class TestConfigDataLoader implements ConfigDataLoader<ConfigDataLocation> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConfigData load(ConfigDataLocation location) throws IOException {
|
public ConfigData load(ConfigDataLoaderContext context, ConfigDataLocation location) throws IOException {
|
||||||
return createConfigData(this, location);
|
return createConfigData(this, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +142,7 @@ class ConfigDataLoadersTests {
|
|||||||
static class NonLoadableConfigDataLoader extends TestConfigDataLoader {
|
static class NonLoadableConfigDataLoader extends TestConfigDataLoader {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isLoadable(ConfigDataLocation location) {
|
public boolean isLoadable(ConfigDataLoaderContext context, ConfigDataLocation location) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +151,7 @@ class ConfigDataLoadersTests {
|
|||||||
static class SpecificConfigDataLoader implements ConfigDataLoader<TestConfigDataLocation> {
|
static class SpecificConfigDataLoader implements ConfigDataLoader<TestConfigDataLocation> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConfigData load(TestConfigDataLocation location) throws IOException {
|
public ConfigData load(ConfigDataLoaderContext context, TestConfigDataLocation location) throws IOException {
|
||||||
return createConfigData(this, location);
|
return createConfigData(this, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +160,7 @@ class ConfigDataLoadersTests {
|
|||||||
static class OtherConfigDataLoader implements ConfigDataLoader<OtherConfigDataLocation> {
|
static class OtherConfigDataLoader implements ConfigDataLoader<OtherConfigDataLocation> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConfigData load(OtherConfigDataLocation location) throws IOException {
|
public ConfigData load(ConfigDataLoaderContext context, OtherConfigDataLocation location) throws IOException {
|
||||||
return createConfigData(this, location);
|
return createConfigData(this, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,9 +31,9 @@ import static org.mockito.Mockito.mock;
|
|||||||
*/
|
*/
|
||||||
class ConfigDataLocationResolverTests {
|
class ConfigDataLocationResolverTests {
|
||||||
|
|
||||||
ConfigDataLocationResolver<?> resolver = new TestConfigDataLocationResolver();
|
private ConfigDataLocationResolver<?> resolver = new TestConfigDataLocationResolver();
|
||||||
|
|
||||||
ConfigDataLocationResolverContext context = mock(ConfigDataLocationResolverContext.class);
|
private ConfigDataLocationResolverContext context = mock(ConfigDataLocationResolverContext.class);
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void resolveProfileSpecificReturnsEmptyList() {
|
void resolveProfileSpecificReturnsEmptyList() {
|
||||||
|
@ -28,6 +28,7 @@ import org.springframework.core.env.PropertySource;
|
|||||||
import org.springframework.util.FileCopyUtils;
|
import org.springframework.util.FileCopyUtils;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link ConfigTreeConfigDataLoader}.
|
* Tests for {@link ConfigTreeConfigDataLoader}.
|
||||||
@ -39,6 +40,8 @@ public class ConfigTreeConfigDataLoaderTests {
|
|||||||
|
|
||||||
private ConfigTreeConfigDataLoader loader = new ConfigTreeConfigDataLoader();
|
private ConfigTreeConfigDataLoader loader = new ConfigTreeConfigDataLoader();
|
||||||
|
|
||||||
|
private ConfigDataLoaderContext loaderContext = mock(ConfigDataLoaderContext.class);
|
||||||
|
|
||||||
@TempDir
|
@TempDir
|
||||||
Path directory;
|
Path directory;
|
||||||
|
|
||||||
@ -48,7 +51,7 @@ public class ConfigTreeConfigDataLoaderTests {
|
|||||||
file.getParentFile().mkdirs();
|
file.getParentFile().mkdirs();
|
||||||
FileCopyUtils.copy("world".getBytes(StandardCharsets.UTF_8), file);
|
FileCopyUtils.copy("world".getBytes(StandardCharsets.UTF_8), file);
|
||||||
ConfigTreeConfigDataLocation location = new ConfigTreeConfigDataLocation(this.directory.toString());
|
ConfigTreeConfigDataLocation location = new ConfigTreeConfigDataLocation(this.directory.toString());
|
||||||
ConfigData configData = this.loader.load(location);
|
ConfigData configData = this.loader.load(this.loaderContext, location);
|
||||||
assertThat(configData.getPropertySources().size()).isEqualTo(1);
|
assertThat(configData.getPropertySources().size()).isEqualTo(1);
|
||||||
PropertySource<?> source = configData.getPropertySources().get(0);
|
PropertySource<?> source = configData.getPropertySources().get(0);
|
||||||
assertThat(source.getName()).isEqualTo("Config tree '" + this.directory.toString() + "'");
|
assertThat(source.getName()).isEqualTo("Config tree '" + this.directory.toString() + "'");
|
||||||
|
@ -26,6 +26,7 @@ import org.springframework.core.env.PropertySource;
|
|||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link ResourceConfigDataLoader}.
|
* Tests for {@link ResourceConfigDataLoader}.
|
||||||
@ -37,11 +38,13 @@ public class ResourceConfigDataLoaderTests {
|
|||||||
|
|
||||||
private ResourceConfigDataLoader loader = new ResourceConfigDataLoader();
|
private ResourceConfigDataLoader loader = new ResourceConfigDataLoader();
|
||||||
|
|
||||||
|
private ConfigDataLoaderContext loaderContext = mock(ConfigDataLoaderContext.class);
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void loadWhenLocationResultsInMultiplePropertySourcesAddsAllToConfigData() throws IOException {
|
void loadWhenLocationResultsInMultiplePropertySourcesAddsAllToConfigData() throws IOException {
|
||||||
ResourceConfigDataLocation location = new ResourceConfigDataLocation("application.yml",
|
ResourceConfigDataLocation location = new ResourceConfigDataLocation("application.yml",
|
||||||
new ClassPathResource("configdata/yaml/application.yml"), new YamlPropertySourceLoader());
|
new ClassPathResource("configdata/yaml/application.yml"), new YamlPropertySourceLoader());
|
||||||
ConfigData configData = this.loader.load(location);
|
ConfigData configData = this.loader.load(this.loaderContext, location);
|
||||||
assertThat(configData.getPropertySources().size()).isEqualTo(2);
|
assertThat(configData.getPropertySources().size()).isEqualTo(2);
|
||||||
PropertySource<?> source1 = configData.getPropertySources().get(0);
|
PropertySource<?> source1 = configData.getPropertySources().get(0);
|
||||||
PropertySource<?> source2 = configData.getPropertySources().get(1);
|
PropertySource<?> source2 = configData.getPropertySources().get(1);
|
||||||
@ -56,7 +59,7 @@ public class ResourceConfigDataLoaderTests {
|
|||||||
ResourceConfigDataLocation location = new ResourceConfigDataLocation("testproperties.properties",
|
ResourceConfigDataLocation location = new ResourceConfigDataLocation("testproperties.properties",
|
||||||
new ClassPathResource("config/0-empty/testproperties.properties"),
|
new ClassPathResource("config/0-empty/testproperties.properties"),
|
||||||
new PropertiesPropertySourceLoader());
|
new PropertiesPropertySourceLoader());
|
||||||
ConfigData configData = this.loader.load(location);
|
ConfigData configData = this.loader.load(this.loaderContext, location);
|
||||||
assertThat(configData.getPropertySources().size()).isEqualTo(0);
|
assertThat(configData.getPropertySources().size()).isEqualTo(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* 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.context.config;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.core.env.MapPropertySource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test classes used with
|
||||||
|
* {@link ConfigDataEnvironmentPostProcessorBootstrapRegistryIntegrationTests} to show how
|
||||||
|
* a bootstrap registry can be used. This example will create helper instances during
|
||||||
|
* result and load. It also shows how the helper can ultimately be registered as a bean.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
class TestConfigDataBootstrap {
|
||||||
|
|
||||||
|
static class LocationResolver implements ConfigDataLocationResolver<Location> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isResolvable(ConfigDataLocationResolverContext context, String location) {
|
||||||
|
return location.startsWith("testbootstrap:");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Location> resolve(ConfigDataLocationResolverContext context, String location) {
|
||||||
|
ResolverHelper helper = context.getBootstrapRegistry().get(ResolverHelper.class,
|
||||||
|
() -> new ResolverHelper(location));
|
||||||
|
return Collections.singletonList(new Location(helper));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Loader implements ConfigDataLoader<Location> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConfigData load(ConfigDataLoaderContext context, Location location) throws IOException {
|
||||||
|
context.getBootstrapRegistry().get(LoaderHelper.class, () -> new LoaderHelper(location),
|
||||||
|
LoaderHelper::addToContext);
|
||||||
|
return new ConfigData(
|
||||||
|
Collections.singleton(new MapPropertySource("loaded", Collections.singletonMap("test", "test"))));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Location extends ConfigDataLocation {
|
||||||
|
|
||||||
|
private final ResolverHelper resolverHelper;
|
||||||
|
|
||||||
|
Location(ResolverHelper resolverHelper) {
|
||||||
|
this.resolverHelper = resolverHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "test";
|
||||||
|
}
|
||||||
|
|
||||||
|
ResolverHelper getResolverHelper() {
|
||||||
|
return this.resolverHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ResolverHelper {
|
||||||
|
|
||||||
|
private final String location;
|
||||||
|
|
||||||
|
ResolverHelper(String location) {
|
||||||
|
this.location = location;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getLocation() {
|
||||||
|
return this.location;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class LoaderHelper {
|
||||||
|
|
||||||
|
private final Location location;
|
||||||
|
|
||||||
|
LoaderHelper(Location location) {
|
||||||
|
this.location = location;
|
||||||
|
}
|
||||||
|
|
||||||
|
Location getLocation() {
|
||||||
|
return this.location;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addToContext(ConfigurableApplicationContext context, LoaderHelper loaderHelper) {
|
||||||
|
context.getBeanFactory().registerSingleton("loaderHelper", loaderHelper);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,3 +1,9 @@
|
|||||||
org.springframework.boot.env.PropertySourceLoader=\
|
org.springframework.boot.env.PropertySourceLoader=\
|
||||||
org.springframework.boot.context.config.TestPropertySourceLoader1,\
|
org.springframework.boot.context.config.TestPropertySourceLoader1,\
|
||||||
org.springframework.boot.context.config.TestPropertySourceLoader2
|
org.springframework.boot.context.config.TestPropertySourceLoader2
|
||||||
|
|
||||||
|
org.springframework.boot.context.config.ConfigDataLocationResolver=\
|
||||||
|
org.springframework.boot.context.config.TestConfigDataBootstrap.LocationResolver
|
||||||
|
|
||||||
|
org.springframework.boot.context.config.ConfigDataLoader=\
|
||||||
|
org.springframework.boot.context.config.TestConfigDataBootstrap.Loader
|
@ -0,0 +1 @@
|
|||||||
|
spring.config.import=testbootstrap:test
|
Loading…
Reference in New Issue
Block a user