Make late Environment changes appear in ConfigurationProperties

This commit is contained in:
Dave Syer
2014-06-06 09:40:56 +01:00
parent 37121e69e6
commit 7c72e3342e

View File

@@ -17,6 +17,7 @@
package org.springframework.boot.context.properties;
import java.io.IOException;
import java.util.Iterator;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanCreationException;
@@ -205,15 +206,18 @@ public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProc
try {
PropertySourcesPlaceholderConfigurer configurer = this.beanFactory
.getBean(PropertySourcesPlaceholderConfigurer.class);
return extractPropertySources(configurer);
PropertySources propertySources = configurer.getAppliedPropertySources();
// Flatten the sources into a single list so they can be iterated
return new FlatPropertySources(propertySources);
}
catch (NoSuchBeanDefinitionException ex) {
// Continue if no PropertySourcesPlaceholderConfigurer bean
}
if (this.environment instanceof ConfigurableEnvironment) {
return flattenPropertySources(((ConfigurableEnvironment) this.environment)
.getPropertySources());
MutablePropertySources propertySources = ((ConfigurableEnvironment) this.environment)
.getPropertySources();
return new FlatPropertySources(propertySources);
}
// empty, so not very useful, but fulfils the contract
@@ -229,55 +233,6 @@ public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProc
}
}
/**
* Convenience method to extract PropertySources from an existing (and already
* initialized) PropertySourcesPlaceholderConfigurer. As long as this method is
* executed late enough in the context lifecycle it will come back with data. We can
* rely on the fact that PropertySourcesPlaceholderConfigurer is a
* BeanFactoryPostProcessor and is therefore initialized early.
* @param configurer a PropertySourcesPlaceholderConfigurer
* @return some PropertySources
*/
private PropertySources extractPropertySources(
PropertySourcesPlaceholderConfigurer configurer) {
PropertySources propertySources = configurer.getAppliedPropertySources();
// Flatten the sources into a single list so they can be iterated
return flattenPropertySources(propertySources);
}
/**
* Flatten out a tree of property sources.
* @param propertySources some PropertySources, possibly containing environment
* properties
* @return another PropertySources containing the same properties
*/
private PropertySources flattenPropertySources(PropertySources propertySources) {
MutablePropertySources result = new MutablePropertySources();
for (PropertySource<?> propertySource : propertySources) {
flattenPropertySources(propertySource, result);
}
return result;
}
/**
* Convenience method to allow recursive flattening of property sources.
* @param propertySource a property source to flatten
* @param result the cumulative result
*/
private void flattenPropertySources(PropertySource<?> propertySource,
MutablePropertySources result) {
Object source = propertySource.getSource();
if (source instanceof ConfigurableEnvironment) {
ConfigurableEnvironment environment = (ConfigurableEnvironment) source;
for (PropertySource<?> childSource : environment.getPropertySources()) {
flattenPropertySources(childSource, result);
}
}
else {
result.addLast(propertySource);
}
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
@@ -425,4 +380,60 @@ public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProc
}
/**
* Convenience class to flatten out a tree of property sources without losing the
* reference to the backing data (which can therefore be updated in the background).
*
* @param propertySources some PropertySources, possibly containing environment
* properties
* @return another PropertySources containing the same properties
*/
private static class FlatPropertySources implements PropertySources {
private PropertySources propertySources;
public FlatPropertySources(PropertySources propertySources) {
this.propertySources = propertySources;
}
@Override
public Iterator<PropertySource<?>> iterator() {
MutablePropertySources result = getFlattened();
return result.iterator();
}
@Override
public boolean contains(String name) {
return get(name) != null;
}
@Override
public PropertySource<?> get(String name) {
return getFlattened().get(name);
}
private MutablePropertySources getFlattened() {
MutablePropertySources result = new MutablePropertySources();
for (PropertySource<?> propertySource : propertySources) {
flattenPropertySources(propertySource, result);
}
return result;
}
private void flattenPropertySources(PropertySource<?> propertySource,
MutablePropertySources result) {
Object source = propertySource.getSource();
if (source instanceof ConfigurableEnvironment) {
ConfigurableEnvironment environment = (ConfigurableEnvironment) source;
for (PropertySource<?> childSource : environment.getPropertySources()) {
flattenPropertySources(childSource, result);
}
}
else {
result.addLast(propertySource);
}
}
}
}