Skip to content

Commit 085c617

Browse files
committed
Let spring.profiles.[include|active] accept list as well as comma separated value in bootstrapProperties
Fix GH-1417 Signed-off-by: Yanming Zhou <[email protected]>
1 parent 2904285 commit 085c617

File tree

2 files changed

+36
-21
lines changed

2 files changed

+36
-21
lines changed

spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/config/PropertySourceBootstrapConfiguration.java

+15-19
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2025 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.
@@ -34,6 +34,8 @@
3434
import org.springframework.boot.context.properties.EnableConfigurationProperties;
3535
import org.springframework.boot.context.properties.bind.Bindable;
3636
import org.springframework.boot.context.properties.bind.Binder;
37+
import org.springframework.boot.context.properties.bind.PropertySourcesPlaceholdersResolver;
38+
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
3739
import org.springframework.boot.logging.LogFile;
3840
import org.springframework.boot.logging.LoggingInitializationContext;
3941
import org.springframework.boot.logging.LoggingSystem;
@@ -46,6 +48,7 @@
4648
import org.springframework.context.annotation.Configuration;
4749
import org.springframework.context.event.ContextRefreshedEvent;
4850
import org.springframework.core.Ordered;
51+
import org.springframework.core.ResolvableType;
4952
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
5053
import org.springframework.core.env.AbstractEnvironment;
5154
import org.springframework.core.env.CompositePropertySource;
@@ -54,13 +57,13 @@
5457
import org.springframework.core.env.Environment;
5558
import org.springframework.core.env.MutablePropertySources;
5659
import org.springframework.core.env.PropertySource;
57-
import org.springframework.util.StringUtils;
5860

5961
import static org.springframework.cloud.bootstrap.encrypt.AbstractEnvironmentDecrypt.DECRYPTED_PROPERTY_SOURCE_NAME;
6062
import static org.springframework.core.env.StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME;
6163

6264
/**
6365
* @author Dave Syer
66+
* @author Yanming Zhou
6467
*
6568
*/
6669
@Configuration(proxyBeanMethods = false)
@@ -294,6 +297,7 @@ private List<String> addActiveProfilesTo(List<String> profiles, PropertySource<?
294297
return addProfilesTo(profiles, propertySource, AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME, environment);
295298
}
296299

300+
@SuppressWarnings("unchecked")
297301
private <T extends Collection<String>> T addProfilesTo(T profiles, PropertySource<?> propertySource,
298302
String property, ConfigurableEnvironment environment) {
299303
if (propertySource instanceof CompositePropertySource) {
@@ -303,27 +307,19 @@ private <T extends Collection<String>> T addProfilesTo(T profiles, PropertySourc
303307
}
304308
}
305309
else {
306-
Collections.addAll(profiles, getProfilesForValue(propertySource.getProperty(property), environment));
310+
// bootstrapProperties is loaded as package-private
311+
// ConfigurationPropertySourcesPropertySource
312+
ResolvableType requiredType = ResolvableType.forClassWithGenerics(PropertySource.class,
313+
ResolvableType.forClassWithGenerics(Iterable.class, ConfigurationPropertySource.class));
314+
if (requiredType.isInstance(propertySource)) {
315+
Binder binder = new Binder((Iterable<ConfigurationPropertySource>) propertySource.getSource(),
316+
new PropertySourcesPlaceholdersResolver(environment));
317+
binder.bind(property, Bindable.listOf(String.class)).ifBound(profiles::addAll);
318+
}
307319
}
308320
return profiles;
309321
}
310322

311-
private String[] getProfilesForValue(Object property, ConfigurableEnvironment environment) {
312-
final String value = (property == null ? null : property.toString());
313-
return property == null ? new String[0] : resolvePlaceholdersInProfiles(value, environment);
314-
}
315-
316-
private String[] resolvePlaceholdersInProfiles(String profiles, ConfigurableEnvironment environment) {
317-
return Arrays.stream(StringUtils.tokenizeToStringArray(profiles, ",")).map(s -> {
318-
if (s.startsWith("${") && s.endsWith("}")) {
319-
return environment.resolvePlaceholders(s);
320-
}
321-
else {
322-
return s;
323-
}
324-
}).toArray(String[]::new);
325-
}
326-
327323
/*
328324
* The ConextRefreshedEvent gets called at the end of the boostrap phase after config
329325
* data is loaded during bootstrap. This will run and do an "initial fetch" of

spring-cloud-context/src/test/java/org/springframework/cloud/bootstrap/config/BootstrapConfigurationTests.java

+21-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2025 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.
@@ -49,6 +49,7 @@
4949

5050
/**
5151
* @author Dave Syer
52+
* @author Yanming Zhou
5253
*
5354
*/
5455
public class BootstrapConfigurationTests {
@@ -597,6 +598,15 @@ public void includeProfileFromBootstrapPropertySourceWithAppContext() {
597598

598599
private void includeProfileFromBootstrapPropertySource(String... properties) {
599600
PropertySourceConfiguration.MAP.put("spring.profiles.include", "bar,baz");
601+
assertIncludeProfileFromBootstrapPropertySource(properties);
602+
603+
PropertySourceConfiguration.MAP.clear();
604+
PropertySourceConfiguration.MAP.put("spring.profiles.include[0]", "bar");
605+
PropertySourceConfiguration.MAP.put("spring.profiles.include[1]", "baz");
606+
assertIncludeProfileFromBootstrapPropertySource(properties);
607+
}
608+
609+
private void assertIncludeProfileFromBootstrapPropertySource(String... properties) {
600610
this.context = new SpringApplicationBuilder().web(WebApplicationType.NONE)
601611
.properties(properties)
602612
.profiles("foo")
@@ -622,13 +632,22 @@ public void activeProfileFromBootstrapPropertySourceWithAppContext() {
622632

623633
private void activeProfileFromBootstrapPropertySource(String... properties) {
624634
PropertySourceConfiguration.MAP.put("spring.profiles.active", "bar,baz");
635+
assertActiveProfileFromBootstrapPropertySource(properties);
636+
637+
PropertySourceConfiguration.MAP.clear();
638+
PropertySourceConfiguration.MAP.put("spring.profiles.active[0]", "bar");
639+
PropertySourceConfiguration.MAP.put("spring.profiles.active[1]", "baz");
640+
assertActiveProfileFromBootstrapPropertySource(properties);
641+
642+
}
643+
644+
private void assertActiveProfileFromBootstrapPropertySource(String... properties) {
625645
this.context = new SpringApplicationBuilder().web(WebApplicationType.NONE)
626646
.properties(properties)
627647
.profiles("foo")
628648
.sources(BareConfiguration.class)
629649
.run();
630650
then(this.context.getEnvironment().acceptsProfiles("baz", "bar", "foo")).isTrue();
631-
632651
}
633652

634653
@Test

0 commit comments

Comments
 (0)