org.springframework.context.support.PropertySourcesPlaceholderConfigurer Maven / Gradle / Ivy
Show all versions of spring-context Show documentation
/*
* Copyright 2002-2013 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.context.support;
import java.io.IOException;
import java.util.Properties;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PlaceholderConfigurerSupport;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.ConfigurablePropertyResolver;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.env.PropertySources;
import org.springframework.core.env.PropertySourcesPropertyResolver;
import org.springframework.util.Assert;
import org.springframework.util.StringValueResolver;
/**
* Specialization of {@link org.springframework.beans.factory.config.PlaceholderConfigurerSupport
* PlaceholderConfigurerSupport} that resolves ${...} placeholders within bean definition
* property values and {@code @Value} annotations against the current Spring {@link
* Environment} and its set of {@link PropertySources}.
*
* This class is designed as a general replacement for {@code
* PropertyPlaceholderConfigurer} in Spring 3.1 applications. It is used by default to
* support the {@code property-placeholder} element in working against the
* spring-context-3.1 XSD, whereas spring-context versions <= 3.0 default to
* {@code PropertyPlaceholderConfigurer} to ensure backward compatibility. See
* spring-context XSD documentation for complete details.
*
*
Any local properties (e.g. those added via {@link #setProperties},
* {@link #setLocations} et al.) are added as a {@code PropertySource}. Search precedence
* of local properties is based on the value of the {@link #setLocalOverride localOverride}
* property, which is by default {@code false} meaning that local properties are to be
* searched last, after all environment property sources.
*
*
See {@link org.springframework.core.env.ConfigurableEnvironment ConfigurableEnvironment}
* and related Javadoc for details on manipulating environment property sources.
*
* @author Chris Beams
* @since 3.1
* @see org.springframework.core.env.ConfigurableEnvironment
* @see org.springframework.beans.factory.config.PlaceholderConfigurerSupport
* @see org.springframework.beans.factory.config.PropertyPlaceholderConfigurer
*/
public class PropertySourcesPlaceholderConfigurer extends PlaceholderConfigurerSupport
implements EnvironmentAware {
/**
* {@value} is the name given to the {@link PropertySource} for the set of
* {@linkplain #mergeProperties() merged properties} supplied to this configurer.
*/
public static final String LOCAL_PROPERTIES_PROPERTY_SOURCE_NAME = "localProperties";
/**
* {@value} is the name given to the {@link PropertySource} that wraps the
* {@linkplain #setEnvironment environment} supplied to this configurer.
*/
public static final String ENVIRONMENT_PROPERTIES_PROPERTY_SOURCE_NAME = "environmentProperties";
private MutablePropertySources propertySources;
private PropertySources appliedPropertySources;
private Environment environment;
/**
* Customize the set of {@link PropertySources} to be used by this configurer.
* Setting this property indicates that environment property sources and local
* properties should be ignored.
* @see #postProcessBeanFactory
*/
public void setPropertySources(PropertySources propertySources) {
this.propertySources = new MutablePropertySources(propertySources);
}
/**
* {@inheritDoc}
*
{@code PropertySources} from this environment will be searched when replacing ${...} placeholders.
* @see #setPropertySources
* @see #postProcessBeanFactory
*/
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
/**
* {@inheritDoc}
*
Processing occurs by replacing ${...} placeholders in bean definitions by resolving each
* against this configurer's set of {@link PropertySources}, which includes:
*
* - all {@linkplain org.springframework.core.env.ConfigurableEnvironment#getPropertySources
* environment property sources}, if an {@code Environment} {@linkplain #setEnvironment is present}
*
- {@linkplain #mergeProperties merged local properties}, if {@linkplain #setLocation any}
* {@linkplain #setLocations have} {@linkplain #setProperties been}
* {@linkplain #setPropertiesArray specified}
*
- any property sources set by calling {@link #setPropertySources}
*
* If {@link #setPropertySources} is called, environment and local properties will be
* ignored. This method is designed to give the user fine-grained control over property
* sources, and once set, the configurer makes no assumptions about adding additional sources.
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
if (this.propertySources == null) {
this.propertySources = new MutablePropertySources();
if (this.environment != null) {
this.propertySources.addLast(
new PropertySource(ENVIRONMENT_PROPERTIES_PROPERTY_SOURCE_NAME, this.environment) {
@Override
public String getProperty(String key) {
return this.source.getProperty(key);
}
}
);
}
try {
PropertySource> localPropertySource =
new PropertiesPropertySource(LOCAL_PROPERTIES_PROPERTY_SOURCE_NAME, mergeProperties());
if (this.localOverride) {
this.propertySources.addFirst(localPropertySource);
}
else {
this.propertySources.addLast(localPropertySource);
}
}
catch (IOException ex) {
throw new BeanInitializationException("Could not load properties", ex);
}
}
processProperties(beanFactory, new PropertySourcesPropertyResolver(this.propertySources));
this.appliedPropertySources = this.propertySources;
}
/**
* Visit each bean definition in the given bean factory and attempt to replace ${...} property
* placeholders with values from the given properties.
*/
protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
final ConfigurablePropertyResolver propertyResolver) throws BeansException {
propertyResolver.setPlaceholderPrefix(this.placeholderPrefix);
propertyResolver.setPlaceholderSuffix(this.placeholderSuffix);
propertyResolver.setValueSeparator(this.valueSeparator);
StringValueResolver valueResolver = new StringValueResolver() {
@Override
public String resolveStringValue(String strVal) {
String resolved = ignoreUnresolvablePlaceholders ?
propertyResolver.resolvePlaceholders(strVal) :
propertyResolver.resolveRequiredPlaceholders(strVal);
return (resolved.equals(nullValue) ? null : resolved);
}
};
doProcessProperties(beanFactoryToProcess, valueResolver);
}
/**
* Implemented for compatibility with {@link org.springframework.beans.factory.config.PlaceholderConfigurerSupport}.
* @deprecated in favor of {@link #processProperties(ConfigurableListableBeanFactory, ConfigurablePropertyResolver)}
* @throws UnsupportedOperationException
*/
@Override
@Deprecated
protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props) {
throw new UnsupportedOperationException(
"Call processProperties(ConfigurableListableBeanFactory, ConfigurablePropertyResolver) instead");
}
/**
* Returns the property sources that were actually applied during
* {@link #postProcessBeanFactory(ConfigurableListableBeanFactory) post-processing}.
* @return the property sources that were applied
* @throws IllegalStateException if the property sources have not yet been applied
* @since 4.0
*/
public PropertySources getAppliedPropertySources() throws IllegalStateException {
Assert.state(this.appliedPropertySources != null, "PropertySources have not get been applied");
return this.appliedPropertySources;
}
}