Skip to content

Commit 3352024

Browse files
philwebbmbhave
andcommitted
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 <[email protected]>
1 parent 44f1836 commit 3352024

File tree

96 files changed

+8130
-168
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

96 files changed

+8130
-168
lines changed

spring-boot-project/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/RemoteSpringApplication.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2019 the original author or authors.
2+
* Copyright 2012-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -25,13 +25,14 @@
2525
import org.springframework.boot.SpringApplication;
2626
import org.springframework.boot.WebApplicationType;
2727
import org.springframework.boot.context.config.AnsiOutputApplicationListener;
28-
import org.springframework.boot.context.config.ConfigFileApplicationListener;
28+
import org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor;
2929
import org.springframework.boot.context.logging.ClasspathLoggingApplicationListener;
3030
import org.springframework.boot.context.logging.LoggingApplicationListener;
3131
import org.springframework.boot.devtools.remote.client.RemoteClientConfiguration;
3232
import org.springframework.boot.devtools.restart.RestartInitializer;
3333
import org.springframework.boot.devtools.restart.RestartScopeInitializer;
3434
import org.springframework.boot.devtools.restart.Restarter;
35+
import org.springframework.boot.env.EnvironmentPostProcessorApplicationListener;
3536
import org.springframework.context.ApplicationContextInitializer;
3637
import org.springframework.context.ApplicationListener;
3738
import org.springframework.core.io.ClassPathResource;
@@ -71,7 +72,7 @@ private Collection<ApplicationContextInitializer<?>> getInitializers() {
7172
private Collection<ApplicationListener<?>> getListeners() {
7273
List<ApplicationListener<?>> listeners = new ArrayList<>();
7374
listeners.add(new AnsiOutputApplicationListener());
74-
listeners.add(new ConfigFileApplicationListener());
75+
listeners.add(new EnvironmentPostProcessorApplicationListener(ConfigDataEnvironmentPostProcessor.class));
7576
listeners.add(new ClasspathLoggingApplicationListener());
7677
listeners.add(new LoggingApplicationListener());
7778
listeners.add(new RemoteUrlPropertyExtractor());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright 2012-2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.test.context;
18+
19+
import java.util.function.Supplier;
20+
21+
import org.springframework.boot.context.config.ConfigData;
22+
import org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor;
23+
import org.springframework.boot.env.DefaultPropertiesPropertySource;
24+
import org.springframework.boot.env.RandomValuePropertySource;
25+
import org.springframework.context.ApplicationContextInitializer;
26+
import org.springframework.context.ConfigurableApplicationContext;
27+
import org.springframework.core.env.ConfigurableEnvironment;
28+
import org.springframework.core.io.ResourceLoader;
29+
import org.springframework.test.context.ContextConfiguration;
30+
31+
/**
32+
* {@link ApplicationContextInitializer} that can be used with the
33+
* {@link ContextConfiguration#initializers()} to trigger loading of {@link ConfigData}
34+
* such as {@literal application.properties}.
35+
*
36+
* @author Phillip Webb
37+
* @since 2.4.0
38+
* @see ConfigDataEnvironmentPostProcessor
39+
*/
40+
public class ConfigDataApplicationContextInitializer
41+
implements ApplicationContextInitializer<ConfigurableApplicationContext> {
42+
43+
@Override
44+
public void initialize(ConfigurableApplicationContext applicationContext) {
45+
ConfigurableEnvironment environment = applicationContext.getEnvironment();
46+
RandomValuePropertySource.addToEnvironment(environment);
47+
new ConfigDataProcessor().addPropertySources(environment, applicationContext);
48+
DefaultPropertiesPropertySource.moveToEnd(environment);
49+
}
50+
51+
private static class ConfigDataProcessor extends ConfigDataEnvironmentPostProcessor {
52+
53+
ConfigDataProcessor() {
54+
super(Supplier::get);
55+
}
56+
57+
void addPropertySources(ConfigurableEnvironment environment, ResourceLoader resourceLoader) {
58+
addPropertySources(environment, resourceLoader, null);
59+
}
60+
61+
}
62+
63+
}

spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/context/ConfigFileApplicationContextInitializer.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2019 the original author or authors.
2+
* Copyright 2012-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,7 +16,6 @@
1616

1717
package org.springframework.boot.test.context;
1818

19-
import org.springframework.boot.context.config.ConfigFileApplicationListener;
2019
import org.springframework.context.ApplicationContextInitializer;
2120
import org.springframework.context.ConfigurableApplicationContext;
2221
import org.springframework.test.context.ContextConfiguration;
@@ -28,14 +27,16 @@
2827
*
2928
* @author Phillip Webb
3029
* @since 1.4.0
31-
* @see ConfigFileApplicationListener
30+
* @see org.springframework.boot.context.config.ConfigFileApplicationListener
31+
* @deprecated since 2.4.0 in favor of {@link ConfigDataApplicationContextInitializer}
3232
*/
33+
@Deprecated
3334
public class ConfigFileApplicationContextInitializer
3435
implements ApplicationContextInitializer<ConfigurableApplicationContext> {
3536

3637
@Override
3738
public void initialize(ConfigurableApplicationContext applicationContext) {
38-
new ConfigFileApplicationListener() {
39+
new org.springframework.boot.context.config.ConfigFileApplicationListener() {
3940
public void apply() {
4041
addPropertySources(applicationContext.getEnvironment(), applicationContext);
4142
addPostProcessors(applicationContext);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright 2012-2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.test.context;
18+
19+
import org.junit.jupiter.api.Test;
20+
import org.junit.jupiter.api.extension.ExtendWith;
21+
22+
import org.springframework.beans.factory.annotation.Autowired;
23+
import org.springframework.context.annotation.Configuration;
24+
import org.springframework.core.env.Environment;
25+
import org.springframework.test.annotation.DirtiesContext;
26+
import org.springframework.test.context.ContextConfiguration;
27+
import org.springframework.test.context.junit.jupiter.SpringExtension;
28+
29+
import static org.assertj.core.api.Assertions.assertThat;
30+
31+
/**
32+
* Tests for {@link ConfigDataApplicationContextInitializer}.
33+
*
34+
* @author Phillip Webb
35+
*/
36+
@ExtendWith(SpringExtension.class)
37+
@DirtiesContext
38+
@ContextConfiguration(classes = ConfigDataApplicationContextInitializerTests.Config.class,
39+
initializers = ConfigDataApplicationContextInitializer.class)
40+
class ConfigDataApplicationContextInitializerTests {
41+
42+
@Autowired
43+
private Environment environment;
44+
45+
@Test
46+
void initializerPopulatesEnvironment() {
47+
assertThat(this.environment.getProperty("foo")).isEqualTo("bucket");
48+
}
49+
50+
@Configuration(proxyBeanMethods = false)
51+
static class Config {
52+
53+
}
54+
55+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright 2012-2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.test.context;
18+
19+
import org.junit.jupiter.api.Test;
20+
import org.junit.jupiter.api.extension.ExtendWith;
21+
22+
import org.springframework.beans.factory.annotation.Autowired;
23+
import org.springframework.context.annotation.Configuration;
24+
import org.springframework.core.env.Environment;
25+
import org.springframework.test.annotation.DirtiesContext;
26+
import org.springframework.test.context.ContextConfiguration;
27+
import org.springframework.test.context.TestPropertySource;
28+
import org.springframework.test.context.junit.jupiter.SpringExtension;
29+
30+
import static org.assertj.core.api.Assertions.assertThat;
31+
32+
/**
33+
* Tests for {@link ConfigDataApplicationContextInitializer}.
34+
*
35+
* @author Phillip Webb
36+
*/
37+
@ExtendWith(SpringExtension.class)
38+
@DirtiesContext
39+
@TestPropertySource(properties = "spring.config.use-legacy-processing=true")
40+
@ContextConfiguration(classes = ConfigDataApplicationContextInitializerWithLegacySwitchTests.Config.class,
41+
initializers = ConfigDataApplicationContextInitializer.class)
42+
class ConfigDataApplicationContextInitializerWithLegacySwitchTests {
43+
44+
@Autowired
45+
private Environment environment;
46+
47+
@Test
48+
void initializerPopulatesEnvironment() {
49+
assertThat(this.environment.getProperty("foo")).isEqualTo("bucket");
50+
}
51+
52+
@Configuration(proxyBeanMethods = false)
53+
static class Config {
54+
55+
}
56+
57+
}

spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/context/ConfigFileApplicationContextInitializerTests.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2019 the original author or authors.
2+
* Copyright 2012-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -33,6 +33,8 @@
3333
*
3434
* @author Phillip Webb
3535
*/
36+
@Deprecated
37+
@SuppressWarnings("deprecation")
3638
@ExtendWith(SpringExtension.class)
3739
@DirtiesContext
3840
@ContextConfiguration(classes = ConfigFileApplicationContextInitializerTests.Config.class,

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import java.util.Collection;
2424
import java.util.Collections;
2525
import java.util.HashMap;
26-
import java.util.HashSet;
2726
import java.util.LinkedHashSet;
2827
import java.util.List;
2928
import java.util.Map;
@@ -237,7 +236,7 @@ public class SpringApplication {
237236

238237
private Map<String, Object> defaultProperties;
239238

240-
private Set<String> additionalProfiles = new HashSet<>();
239+
private Set<String> additionalProfiles = Collections.emptySet();
241240

242241
private boolean allowBeanDefinitionOverriding;
243242

@@ -352,6 +351,7 @@ private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners
352351
ConfigurationPropertySources.attach(environment);
353352
listeners.environmentPrepared(environment);
354353
DefaultPropertiesPropertySource.moveToEnd(environment);
354+
configureAdditionalProfiles(environment);
355355
bindToSpringApplication(environment);
356356
if (!this.isCustomEnvironment) {
357357
environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
@@ -527,9 +527,16 @@ protected void configurePropertySources(ConfigurableEnvironment environment, Str
527527
* @see org.springframework.boot.context.config.ConfigFileApplicationListener
528528
*/
529529
protected void configureProfiles(ConfigurableEnvironment environment, String[] args) {
530-
Set<String> profiles = new LinkedHashSet<>(this.additionalProfiles);
531-
profiles.addAll(Arrays.asList(environment.getActiveProfiles()));
532-
environment.setActiveProfiles(StringUtils.toStringArray(profiles));
530+
}
531+
532+
private void configureAdditionalProfiles(ConfigurableEnvironment environment) {
533+
if (!CollectionUtils.isEmpty(this.additionalProfiles)) {
534+
Set<String> profiles = new LinkedHashSet<>(Arrays.asList(environment.getActiveProfiles()));
535+
if (!profiles.containsAll(this.additionalProfiles)) {
536+
profiles.addAll(this.additionalProfiles);
537+
environment.setActiveProfiles(StringUtils.toStringArray(profiles));
538+
}
539+
}
533540
}
534541

535542
private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
@@ -1043,7 +1050,15 @@ public void setDefaultProperties(Properties defaultProperties) {
10431050
* @param profiles the additional profiles to set
10441051
*/
10451052
public void setAdditionalProfiles(String... profiles) {
1046-
this.additionalProfiles = new LinkedHashSet<>(Arrays.asList(profiles));
1053+
this.additionalProfiles = Collections.unmodifiableSet(new LinkedHashSet<>(Arrays.asList(profiles)));
1054+
}
1055+
1056+
/**
1057+
* Return an immutable set of any additional profiles in use.
1058+
* @return the additional profiles
1059+
*/
1060+
public Set<String> getAdditionalProfiles() {
1061+
return this.additionalProfiles;
10471062
}
10481063

10491064
/**

0 commit comments

Comments
 (0)