Skip to content

Commit 479e829

Browse files
committed
Add prefix support for environment variables
Include a filter in ConfigurationPropertiesBindingPostProcessor that checks if the property "spring.property.prefix" exists (not blank) and filter the system properties ensuring that the properties with the prefix are available on property binding. Fixes #3450
1 parent 3b4928c commit 479e829

File tree

3 files changed

+59
-0
lines changed

3 files changed

+59
-0
lines changed

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

+13
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ public class SpringApplication {
155155

156156
private static final String SYSTEM_PROPERTY_JAVA_AWT_HEADLESS = "java.awt.headless";
157157

158+
public static final String PROPERTY_BINDING_PREFIX_PROPERTY = "spring.property.prefix";
159+
158160
private static final Banner DEFAULT_BANNER = new SpringBootBanner();
159161

160162
private final Log log = LogFactory.getLog(getClass());
@@ -842,6 +844,17 @@ public void setEnvironment(ConfigurableEnvironment environment) {
842844
this.environment = environment;
843845
}
844846

847+
/**
848+
+ * Sets the environment variables prefix that will be used to filter those variables
849+
+ * for this application.
850+
+ * @param environmentPrefix the prefix
851+
+ */
852+
public void setEnvironmentPrefix(String environmentPrefix) {
853+
if(environmentPrefix != null && !"".equals(environmentPrefix)) {
854+
System.setProperty(PROPERTY_BINDING_PREFIX_PROPERTY, environmentPrefix);
855+
}
856+
}
857+
845858
/**
846859
* Returns a mutable set of the sources that will be added to an ApplicationContext
847860
* when {@link #run(String...)} is called.

spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBindingPostProcessor.java

+32
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.boot.context.properties;
1818

1919
import java.io.IOException;
20+
import java.util.HashMap;
2021
import java.util.Iterator;
2122
import java.util.Map;
2223

@@ -29,6 +30,7 @@
2930
import org.springframework.beans.factory.ListableBeanFactory;
3031
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
3132
import org.springframework.beans.factory.config.BeanPostProcessor;
33+
import org.springframework.boot.SpringApplication;
3234
import org.springframework.boot.bind.PropertiesConfigurationFactory;
3335
import org.springframework.boot.env.PropertySourcesLoader;
3436
import org.springframework.context.ApplicationContext;
@@ -49,6 +51,7 @@
4951
import org.springframework.core.env.PropertySource;
5052
import org.springframework.core.env.PropertySources;
5153
import org.springframework.core.env.StandardEnvironment;
54+
import org.springframework.core.env.SystemEnvironmentPropertySource;
5255
import org.springframework.core.io.DefaultResourceLoader;
5356
import org.springframework.core.io.Resource;
5457
import org.springframework.core.io.ResourceLoader;
@@ -203,6 +206,13 @@ public void destroy() throws Exception {
203206
}
204207

205208
private PropertySources deducePropertySources() {
209+
String prefix = this.environment
210+
.getProperty(SpringApplication.PROPERTY_BINDING_PREFIX_PROPERTY, "");
211+
if (prefix != null && !"".equals(prefix)) {
212+
filterSystemEnvironmentPropertySourceByPrefix(
213+
(ConfigurableEnvironment) this.environment, prefix);
214+
}
215+
206216
PropertySourcesPlaceholderConfigurer configurer = getSinglePropertySourcesPlaceholderConfigurer();
207217
if (configurer != null) {
208218
// Flatten the sources into a single list so they can be iterated
@@ -233,6 +243,28 @@ private PropertySourcesPlaceholderConfigurer getSinglePropertySourcesPlaceholder
233243
return null;
234244
}
235245

246+
private void filterSystemEnvironmentPropertySourceByPrefix(
247+
ConfigurableEnvironment environment, String prefix) {
248+
final Map<String, Object> environmentProperties = environment.getSystemProperties();
249+
final Map<String, Object> filteredSystemProperties = new HashMap<String, Object>(
250+
environmentProperties.size());
251+
252+
for (String key : environmentProperties.keySet()) {
253+
if (key.startsWith(prefix)) {
254+
filteredSystemProperties.put(key.substring(prefix.length()),
255+
environmentProperties.get(key));
256+
} else {
257+
filteredSystemProperties.put(key, environmentProperties.get(key));
258+
}
259+
}
260+
261+
environment.getPropertySources()
262+
.replace(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME,
263+
new SystemEnvironmentPropertySource(
264+
StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME,
265+
filteredSystemProperties));
266+
}
267+
236268
private <T> T getOptionalBean(String name, Class<T> type) {
237269
try {
238270
return this.beanFactory.getBean(name, type);

spring-boot/src/test/java/org/springframework/boot/context/properties/EnableConfigurationPropertiesTests.java

+14
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.junit.Test;
3131
import org.junit.rules.ExpectedException;
3232
import org.springframework.beans.factory.annotation.Autowired;
33+
import org.springframework.boot.SpringApplication;
3334
import org.springframework.boot.test.EnvironmentTestUtils;
3435
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
3536
import org.springframework.context.annotation.Bean;
@@ -79,6 +80,19 @@ public void testSystemPropertiesBinding() {
7980
assertEquals("foo", this.context.getBean(TestProperties.class).name);
8081
}
8182

83+
@Test
84+
public void testSystemPropertiesWithPrefixBinding() {
85+
this.context.register(TestConfiguration.class);
86+
System.setProperty(SpringApplication.PROPERTY_BINDING_PREFIX_PROPERTY, "bar_");
87+
System.setProperty("bar_name", "foo");
88+
this.context.refresh();
89+
assertEquals(1, this.context.getBeanNamesForType(TestProperties.class).length);
90+
assertEquals("foo", this.context.getBean(TestProperties.class).name);
91+
//Assert that the environment system property still has the prefix
92+
assertEquals("foo",
93+
this.context.getEnvironment().getSystemProperties().get("bar_name"));
94+
}
95+
8296
@Test
8397
public void testNestedSystemPropertiesBinding() {
8498
this.context.register(NestedConfiguration.class);

0 commit comments

Comments
 (0)