Refactor PropertySourcesDeducer

Prior to the changes that fixed #12451,
`FilteredPropertySources` and `CompositePropertySources` were required
by the `PropertySourcesDeducer` to ensure that configuration properties binding
could see changes to the environment even when there was a
PropertySourcesPlaceholderConfigurer in the context. #12451 changed the way
property sources are adapted by `SpringConfigurationPropertySources`, removing the
need for `FilteredPropertySources` and `CompositePropertySources`.

Fixes gh-13738
pull/14003/head
Madhura Bhave 6 years ago
parent 7e2494ebdd
commit 16aff4cd2c

@ -1,70 +0,0 @@
/*
* Copyright 2012-2018 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.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))
.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;
}
}

@ -1,74 +0,0 @@
/*
* 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.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 PropertySources delegate;
private final Set<String> filtered;
FilteredPropertySources(PropertySources delegate, String... filtered) {
this.delegate = delegate;
this.filtered = new HashSet<>(Arrays.asList(filtered));
}
@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;
}
@Override
public Iterator<PropertySource<?>> iterator() {
return StreamSupport.stream(this.delegate.spliterator(), false)
.filter(this::included).iterator();
}
private boolean included(PropertySource<?> propertySource) {
return included(propertySource.getName());
}
private boolean included(String name) {
return (!this.filtered.contains(name));
}
}

@ -27,7 +27,6 @@ import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.core.env.MutablePropertySources; import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySources; import org.springframework.core.env.PropertySources;
import org.springframework.util.Assert;
/** /**
* Utility to deduce the {@link PropertySources} to use for configuration binding. * Utility to deduce the {@link PropertySources} to use for configuration binding.
@ -45,20 +44,16 @@ class PropertySourcesDeducer {
} }
public PropertySources getPropertySources() { public PropertySources getPropertySources() {
MutablePropertySources environmentPropertySources = extractEnvironmentPropertySources(); PropertySourcesPlaceholderConfigurer configurer = getSinglePropertySourcesPlaceholderConfigurer();
PropertySourcesPlaceholderConfigurer placeholderConfigurer = getSinglePropertySourcesPlaceholderConfigurer(); if (configurer != null) {
if (placeholderConfigurer == null) { return configurer.getAppliedPropertySources();
Assert.state(environmentPropertySources != null,
"Unable to obtain PropertySources from "
+ "PropertySourcesPlaceholderConfigurer or Environment");
return environmentPropertySources;
} }
PropertySources appliedPropertySources = placeholderConfigurer MutablePropertySources sources = extractEnvironmentPropertySources();
.getAppliedPropertySources(); if (sources != null) {
if (environmentPropertySources == null) { return sources;
return appliedPropertySources;
} }
return merge(environmentPropertySources, appliedPropertySources); throw new IllegalStateException("Unable to obtain PropertySources from "
+ "PropertySourcesPlaceholderConfigurer or Environment");
} }
private MutablePropertySources extractEnvironmentPropertySources() { private MutablePropertySources extractEnvironmentPropertySources() {
@ -84,12 +79,4 @@ class PropertySourcesDeducer {
return null; return null;
} }
private PropertySources merge(PropertySources environmentPropertySources,
PropertySources appliedPropertySources) {
FilteredPropertySources filtered = new FilteredPropertySources(
appliedPropertySources,
PropertySourcesPlaceholderConfigurer.ENVIRONMENT_PROPERTIES_PROPERTY_SOURCE_NAME);
return new CompositePropertySources(filtered, environmentPropertySources);
}
} }

@ -1,144 +0,0 @@
/*
* 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);
}
}

@ -25,6 +25,7 @@ import java.util.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties;
import java.util.Set; import java.util.Set;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
@ -352,6 +353,15 @@ public class ConfigurationPropertiesTests {
assertThat(bean.getValue()).isEqualTo("foo"); assertThat(bean.getValue()).isEqualTo("foo");
} }
@Test
public void loadWithPropertyPlaceholderShouldNotAlterPropertySourceOrder() {
load(WithPropertyPlaceholderWithLocalPropertiesValueConfiguration.class,
"com.example.bar=a");
SimplePrefixedProperties bean = this.context
.getBean(SimplePrefixedProperties.class);
assertThat(bean.getBar()).isEqualTo("a");
}
@Test @Test
public void loadWhenHasPostConstructShouldTriggerPostConstructWithBoundBean() { public void loadWhenHasPostConstructShouldTriggerPostConstructWithBoundBean() {
MockEnvironment environment = new MockEnvironment(); MockEnvironment environment = new MockEnvironment();
@ -959,6 +969,21 @@ public class ConfigurationPropertiesTests {
} }
@Configuration
@EnableConfigurationProperties(SimplePrefixedProperties.class)
static class WithPropertyPlaceholderWithLocalPropertiesValueConfiguration {
@Bean
public static PropertySourcesPlaceholderConfigurer configurer() {
PropertySourcesPlaceholderConfigurer placeholderConfigurer = new PropertySourcesPlaceholderConfigurer();
Properties properties = new Properties();
properties.put("com.example.bar", "b");
placeholderConfigurer.setProperties(properties);
return placeholderConfigurer;
}
}
@Configuration @Configuration
@EnableConfigurationProperties @EnableConfigurationProperties
static class WithFactoryBeanConfiguration { static class WithFactoryBeanConfiguration {

@ -1,85 +0,0 @@
/*
* 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…
Cancel
Save