Fix ordering problem in PropertySourcesPropertyValues

This affected @ConfigurationProperties binding whenever there
were multiple PropertySources (from any source) in the
Environment and mor ethan one carried a value for a particular
key. The rules for override are clear in Environment.getProperty()
but they were being violated by the PropertySourcesPropertyValues.

Fixes gh-916
This commit is contained in:
Dave Syer
2014-05-23 16:45:43 +01:00
parent 28f88562f2
commit edb493044a
5 changed files with 144 additions and 4 deletions

View File

@@ -88,8 +88,10 @@ public class PropertySourcesPropertyValues implements PropertyValues {
catch (RuntimeException ex) {
// Probably could not resolve placeholders, ignore it here
}
this.propertyValues.put(propertyName, new PropertyValue(
propertyName, value));
if (!this.propertyValues.containsKey(propertyName)) {
this.propertyValues.put(propertyName, new PropertyValue(
propertyName, value));
}
}
}
}
@@ -99,13 +101,13 @@ public class PropertySourcesPropertyValues implements PropertyValues {
for (String propertyName : exacts) {
Object value;
value = source.getProperty(propertyName);
if (value != null) {
if (value != null && !this.propertyValues.containsKey(propertyName)) {
this.propertyValues.put(propertyName, new PropertyValue(
propertyName, value));
continue;
}
value = source.getProperty(propertyName.toUpperCase());
if (value != null) {
if (value != null && !this.propertyValues.containsKey(propertyName)) {
this.propertyValues.put(propertyName, new PropertyValue(
propertyName, value));
continue;

View File

@@ -0,0 +1,72 @@
package org.springframework.boot.bind;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.bind.PropertySourcesBindingTests.TestConfig;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.PropertySources;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = TestConfig.class)
@IntegrationTest
public class PropertySourcesBindingTests {
@Value("${foo:}")
private String foo;
@Autowired
private Wrapper properties;
@Test
public void overridingOfPropertiesWorksAsExpected() {
assertThat(this.foo, is(this.properties.getFoo()));
}
@Import({ SomeConfig.class })
@PropertySources({ @PropertySource("classpath:/override.properties"),
@PropertySource("classpath:/some.properties") })
@Configuration
@EnableConfigurationProperties(Wrapper.class)
public static class TestConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
@Configuration
@PropertySources({ @PropertySource("classpath:/override.properties"),
@PropertySource("classpath:/some.properties") })
public static class SomeConfig {
}
@ConfigurationProperties
public static class Wrapper {
private String foo;
public String getFoo() {
return this.foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
}
}

View File

@@ -0,0 +1,64 @@
package org.springframework.boot.bind;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.bind.SimplerPropertySourcesBindingTests.TestConfig;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.PropertySources;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = TestConfig.class)
@IntegrationTest
public class SimplerPropertySourcesBindingTests {
@Value("${foo:}")
private String foo;
@Autowired
private Wrapper properties;
@Test
public void overridingOfPropertiesWorksAsExpected() {
assertThat(this.foo, is(this.properties.getFoo()));
}
@PropertySources({ @PropertySource("classpath:/override.properties"),
@PropertySource("classpath:/some.properties") })
@Configuration
@EnableConfigurationProperties(Wrapper.class)
public static class TestConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
@ConfigurationProperties
public static class Wrapper {
private String foo;
public String getFoo() {
return this.foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
}
}

View File

@@ -0,0 +1 @@
foo=bar

View File

@@ -0,0 +1 @@
foo=spam