Make configuration properties binding always uses current environment
Previously, configuration properties binding would only see changes to the environment if there was no PropertySourcesPlaceholderConfigurer in the context. This happened because PropertySourcesPlaceholderConfigurer wrapped the Environment in a PropertySource, effectively hiding it from the change tracking performed by SpringConfigurationPropertySources. This commit updates ConfigurationPropertiesBindingPostProcessor so that it ignores the environment property source contained by PropertySourcesPlaceholderConfigurer and uses a composite of the PropertySourcesPlaceholderConfigurer's other property sources and the Environment's PropertySources instead.pull/10774/merge
parent
ca4d7f7322
commit
85b1511085
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2017 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
|
||||||
|
*
|
||||||
|
* http://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.context.properties;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
|
import org.springframework.core.env.PropertySource;
|
||||||
|
import org.springframework.core.env.PropertySources;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A composite {@link PropertySources} backed by one or more {@code PropertySources}.
|
||||||
|
* Changes to the backing {@code PropertySources} are automatically reflected in the
|
||||||
|
* composite.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
final class CompositePropertySources implements PropertySources {
|
||||||
|
|
||||||
|
private final List<PropertySources> propertySources;
|
||||||
|
|
||||||
|
CompositePropertySources(PropertySources... propertySources) {
|
||||||
|
this.propertySources = Arrays.asList(propertySources);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<PropertySource<?>> iterator() {
|
||||||
|
return this.propertySources.stream()
|
||||||
|
.flatMap((sources) -> StreamSupport.stream(sources.spliterator(), false))
|
||||||
|
.collect(Collectors.toList()).iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(String name) {
|
||||||
|
for (PropertySources sources : this.propertySources) {
|
||||||
|
if (sources.contains(name)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PropertySource<?> get(String name) {
|
||||||
|
for (PropertySources sources : this.propertySources) {
|
||||||
|
PropertySource<?> source = sources.get(name);
|
||||||
|
if (source != null) {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2017 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
|
||||||
|
*
|
||||||
|
* http://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.context.properties;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.StreamSupport;
|
||||||
|
|
||||||
|
import org.springframework.core.env.PropertySource;
|
||||||
|
import org.springframework.core.env.PropertySources;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link PropertySources} decorator that filters property sources by name.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
final class FilteredPropertySources implements PropertySources {
|
||||||
|
|
||||||
|
private final Set<String> filtered;
|
||||||
|
|
||||||
|
private final PropertySources delegate;
|
||||||
|
|
||||||
|
FilteredPropertySources(PropertySources delegate, String... filtered) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
this.filtered = new HashSet<>(Arrays.asList(filtered));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<PropertySource<?>> iterator() {
|
||||||
|
return StreamSupport.stream(this.delegate.spliterator(), false)
|
||||||
|
.filter(this::included).collect(Collectors.toList()).iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean contains(String name) {
|
||||||
|
if (included(name)) {
|
||||||
|
return this.delegate.contains(name);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PropertySource<?> get(String name) {
|
||||||
|
if (included(name)) {
|
||||||
|
return this.delegate.get(name);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean included(PropertySource<?> propertySource) {
|
||||||
|
return included(propertySource.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean included(String name) {
|
||||||
|
return (!this.filtered.contains(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2017 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
|
||||||
|
*
|
||||||
|
* http://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.context.properties;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.springframework.core.env.MapPropertySource;
|
||||||
|
import org.springframework.core.env.MutablePropertySources;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link CompositePropertySources}.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
public class CompositePropertySourcesTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void containsReturnsFalseWithNoBackingSources() {
|
||||||
|
assertThat(new CompositePropertySources().contains("foo")).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getReturnsNullWithNoBackingSources() {
|
||||||
|
assertThat(new CompositePropertySources().get("foo")).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void iteratorIsEmptyWithNoBackingSources() {
|
||||||
|
assertThat(new CompositePropertySources().iterator()).hasSize(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void containsReturnsTrueForPropertySourceFoundInBackingSources() {
|
||||||
|
MutablePropertySources sources = new MutablePropertySources();
|
||||||
|
sources.addFirst(new MapPropertySource("foo", Collections.emptyMap()));
|
||||||
|
assertThat(new CompositePropertySources(sources).contains("foo")).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void containsReturnsFalseForPropertySourceNotFoundInBackingSources() {
|
||||||
|
MutablePropertySources sources = new MutablePropertySources();
|
||||||
|
sources.addFirst(new MapPropertySource("bar", Collections.emptyMap()));
|
||||||
|
assertThat(new CompositePropertySources(sources).contains("foo")).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getReturnsPropertySourceFoundInBackingSources() {
|
||||||
|
MutablePropertySources sources = new MutablePropertySources();
|
||||||
|
MapPropertySource fooSource = new MapPropertySource("foo",
|
||||||
|
Collections.emptyMap());
|
||||||
|
sources.addFirst(fooSource);
|
||||||
|
assertThat(new CompositePropertySources(sources).get("foo")).isEqualTo(fooSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getReturnsNullWhenPropertySourceNotFoundInBackingSources() {
|
||||||
|
MutablePropertySources sources = new MutablePropertySources();
|
||||||
|
sources.addFirst(new MapPropertySource("foo", Collections.emptyMap()));
|
||||||
|
assertThat(new CompositePropertySources(sources).get("bar")).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void iteratorContainsSingleEntryWithSingleBackingSource() {
|
||||||
|
MutablePropertySources sources = new MutablePropertySources();
|
||||||
|
MapPropertySource fooSource = new MapPropertySource("foo",
|
||||||
|
Collections.emptyMap());
|
||||||
|
sources.addFirst(fooSource);
|
||||||
|
assertThat(new CompositePropertySources(sources).iterator())
|
||||||
|
.containsExactly(fooSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void iteratorReflectsOrderingOfSourcesAcrossMultipleBackingSources() {
|
||||||
|
MutablePropertySources sourcesOne = new MutablePropertySources();
|
||||||
|
MapPropertySource fooSource = new MapPropertySource("foo",
|
||||||
|
Collections.emptyMap());
|
||||||
|
sourcesOne.addFirst(fooSource);
|
||||||
|
MapPropertySource barSource = new MapPropertySource("bar",
|
||||||
|
Collections.emptyMap());
|
||||||
|
sourcesOne.addFirst(barSource);
|
||||||
|
MutablePropertySources sourcesTwo = new MutablePropertySources();
|
||||||
|
MapPropertySource bazSource = new MapPropertySource("baz",
|
||||||
|
Collections.emptyMap());
|
||||||
|
sourcesTwo.addFirst(bazSource);
|
||||||
|
assertThat(new CompositePropertySources(sourcesOne, sourcesTwo).iterator())
|
||||||
|
.containsExactly(barSource, fooSource, bazSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void containsReflectsChangesInTheBackingSources() {
|
||||||
|
MutablePropertySources sources = new MutablePropertySources();
|
||||||
|
sources.addFirst(new MapPropertySource("foo", Collections.emptyMap()));
|
||||||
|
assertThat(new CompositePropertySources(sources).contains("bar")).isFalse();
|
||||||
|
MapPropertySource barSource = new MapPropertySource("bar",
|
||||||
|
Collections.emptyMap());
|
||||||
|
sources.addFirst(barSource);
|
||||||
|
assertThat(new CompositePropertySources(sources).contains("bar")).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getReflectsChangesInTheBackingSources() {
|
||||||
|
MutablePropertySources sources = new MutablePropertySources();
|
||||||
|
sources.addFirst(new MapPropertySource("foo", Collections.emptyMap()));
|
||||||
|
assertThat(new CompositePropertySources(sources).get("bar")).isNull();
|
||||||
|
MapPropertySource barSource = new MapPropertySource("bar",
|
||||||
|
Collections.emptyMap());
|
||||||
|
sources.addFirst(barSource);
|
||||||
|
assertThat(new CompositePropertySources(sources).get("bar")).isEqualTo(barSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void iteratorReflectsChangesInTheBackingSources() {
|
||||||
|
MutablePropertySources sources = new MutablePropertySources();
|
||||||
|
MapPropertySource fooSource = new MapPropertySource("foo",
|
||||||
|
Collections.emptyMap());
|
||||||
|
sources.addFirst(fooSource);
|
||||||
|
assertThat(new CompositePropertySources(sources).iterator())
|
||||||
|
.containsExactly(fooSource);
|
||||||
|
MapPropertySource barSource = new MapPropertySource("bar",
|
||||||
|
Collections.emptyMap());
|
||||||
|
sources.addFirst(barSource);
|
||||||
|
assertThat(new CompositePropertySources(sources).iterator())
|
||||||
|
.containsExactly(barSource, fooSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2017 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
|
||||||
|
*
|
||||||
|
* http://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.context.properties;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.springframework.core.env.MapPropertySource;
|
||||||
|
import org.springframework.core.env.MutablePropertySources;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link FilteredPropertySources}.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
public class FilteredPropertySourcesTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getReturnsNullForFilteredSource() {
|
||||||
|
MutablePropertySources delegate = new MutablePropertySources();
|
||||||
|
delegate.addFirst(new MapPropertySource("foo", Collections.emptyMap()));
|
||||||
|
assertThat(new FilteredPropertySources(delegate, "foo").get("foo")).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getReturnsSourceThatIsNotFiltered() {
|
||||||
|
MutablePropertySources delegate = new MutablePropertySources();
|
||||||
|
delegate.addFirst(new MapPropertySource("foo", Collections.emptyMap()));
|
||||||
|
MapPropertySource barSource = new MapPropertySource("bar",
|
||||||
|
Collections.emptyMap());
|
||||||
|
delegate.addFirst(barSource);
|
||||||
|
assertThat(new FilteredPropertySources(delegate, "foo").get("bar"))
|
||||||
|
.isEqualTo(barSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void containsReturnsFalseForFilteredSource() {
|
||||||
|
MutablePropertySources delegate = new MutablePropertySources();
|
||||||
|
delegate.addFirst(new MapPropertySource("foo", Collections.emptyMap()));
|
||||||
|
assertThat(new FilteredPropertySources(delegate, "foo").contains("foo"))
|
||||||
|
.isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void containsReturnsTrueForSourceThatIsNotFiltered() {
|
||||||
|
MutablePropertySources delegate = new MutablePropertySources();
|
||||||
|
delegate.addFirst(new MapPropertySource("foo", Collections.emptyMap()));
|
||||||
|
MapPropertySource barSource = new MapPropertySource("bar",
|
||||||
|
Collections.emptyMap());
|
||||||
|
delegate.addFirst(barSource);
|
||||||
|
assertThat(new FilteredPropertySources(delegate, "foo").contains("bar")).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void iteratorOmitsSourceThatIsFiltered() {
|
||||||
|
MutablePropertySources delegate = new MutablePropertySources();
|
||||||
|
MapPropertySource barSource = new MapPropertySource("bar",
|
||||||
|
Collections.emptyMap());
|
||||||
|
delegate.addFirst(barSource);
|
||||||
|
delegate.addFirst(new MapPropertySource("foo", Collections.emptyMap()));
|
||||||
|
MapPropertySource bazSource = new MapPropertySource("baz",
|
||||||
|
Collections.emptyMap());
|
||||||
|
delegate.addFirst(bazSource);
|
||||||
|
assertThat(new FilteredPropertySources(delegate, "foo").iterator())
|
||||||
|
.containsExactly(bazSource, barSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue