Provide ConfigFileApplicationListener replacement

Deprecate `ConfigFileApplicationListener` and provide a replacement
mechanism that supports arbitrary config data imports.

This commit updates the following areas:

- Extract `EnvironmentPostProcessor` invocation logic from the
  `ConfigFileApplicationListener` to new dedicated listener. Also
  providing support for `Log` injection.

- Extract `RandomPropertySource` adding logic from the
  `ConfigFileApplicationListener` to a dedicated class.

- Migrate to the recently introduced `DefaultPropertiesPropertySource`
  class when moving the defaultProperties `PropertySource`

- Replace processing logic with a phased approach to ensure that
  profile enablement happens in a distinct phase and that profiles
  can no longer be activated on an ad-hoc basis.

- Provide a more predictable and logical import order for processing
  `application.properties` and `application.yml` files.

- Add support for a `spring.config.import` property which can be used
  to import additional config data. Also provide a pluggable API
  allowing third-parties to resolve and load locations themselves.

- Add `spring.config.activate.on-profile` support which replaces the
  existing `spring.profiles` property.

- Add `spring.config.activate.on-cloud-platform` support which allows
  a config data document to be active only on a given cloud platform.

- Support a `spring.config.use-legacy-processing` property allowing the
  previous processing logic to be used.

Closes gh-22497

Co-authored-by: Madhura Bhave <mbhave@vmware.com>
This commit is contained in:
Phillip Webb
2020-07-13 21:19:10 -07:00
parent 44f18362d3
commit 3352024b1c
96 changed files with 8130 additions and 168 deletions

View File

@@ -0,0 +1,63 @@
/*
* 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.test.context;
import java.util.function.Supplier;
import org.springframework.boot.context.config.ConfigData;
import org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor;
import org.springframework.boot.env.DefaultPropertiesPropertySource;
import org.springframework.boot.env.RandomValuePropertySource;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.test.context.ContextConfiguration;
/**
* {@link ApplicationContextInitializer} that can be used with the
* {@link ContextConfiguration#initializers()} to trigger loading of {@link ConfigData}
* such as {@literal application.properties}.
*
* @author Phillip Webb
* @since 2.4.0
* @see ConfigDataEnvironmentPostProcessor
*/
public class ConfigDataApplicationContextInitializer
implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment environment = applicationContext.getEnvironment();
RandomValuePropertySource.addToEnvironment(environment);
new ConfigDataProcessor().addPropertySources(environment, applicationContext);
DefaultPropertiesPropertySource.moveToEnd(environment);
}
private static class ConfigDataProcessor extends ConfigDataEnvironmentPostProcessor {
ConfigDataProcessor() {
super(Supplier::get);
}
void addPropertySources(ConfigurableEnvironment environment, ResourceLoader resourceLoader) {
addPropertySources(environment, resourceLoader, null);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2019 the original author or authors.
* 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.
@@ -16,7 +16,6 @@
package org.springframework.boot.test.context;
import org.springframework.boot.context.config.ConfigFileApplicationListener;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.test.context.ContextConfiguration;
@@ -28,14 +27,16 @@ import org.springframework.test.context.ContextConfiguration;
*
* @author Phillip Webb
* @since 1.4.0
* @see ConfigFileApplicationListener
* @see org.springframework.boot.context.config.ConfigFileApplicationListener
* @deprecated since 2.4.0 in favor of {@link ConfigDataApplicationContextInitializer}
*/
@Deprecated
public class ConfigFileApplicationContextInitializer
implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
new ConfigFileApplicationListener() {
new org.springframework.boot.context.config.ConfigFileApplicationListener() {
public void apply() {
addPropertySources(applicationContext.getEnvironment(), applicationContext);
addPostProcessors(applicationContext);

View File

@@ -0,0 +1,55 @@
/*
* 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.test.context;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link ConfigDataApplicationContextInitializer}.
*
* @author Phillip Webb
*/
@ExtendWith(SpringExtension.class)
@DirtiesContext
@ContextConfiguration(classes = ConfigDataApplicationContextInitializerTests.Config.class,
initializers = ConfigDataApplicationContextInitializer.class)
class ConfigDataApplicationContextInitializerTests {
@Autowired
private Environment environment;
@Test
void initializerPopulatesEnvironment() {
assertThat(this.environment.getProperty("foo")).isEqualTo("bucket");
}
@Configuration(proxyBeanMethods = false)
static class Config {
}
}

View File

@@ -0,0 +1,57 @@
/*
* 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.test.context;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link ConfigDataApplicationContextInitializer}.
*
* @author Phillip Webb
*/
@ExtendWith(SpringExtension.class)
@DirtiesContext
@TestPropertySource(properties = "spring.config.use-legacy-processing=true")
@ContextConfiguration(classes = ConfigDataApplicationContextInitializerWithLegacySwitchTests.Config.class,
initializers = ConfigDataApplicationContextInitializer.class)
class ConfigDataApplicationContextInitializerWithLegacySwitchTests {
@Autowired
private Environment environment;
@Test
void initializerPopulatesEnvironment() {
assertThat(this.environment.getProperty("foo")).isEqualTo("bucket");
}
@Configuration(proxyBeanMethods = false)
static class Config {
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2019 the original author or authors.
* 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.
@@ -33,6 +33,8 @@ import static org.assertj.core.api.Assertions.assertThat;
*
* @author Phillip Webb
*/
@Deprecated
@SuppressWarnings("deprecation")
@ExtendWith(SpringExtension.class)
@DirtiesContext
@ContextConfiguration(classes = ConfigFileApplicationContextInitializerTests.Config.class,