Spring 工具类 : PropertySourcesPlaceholderConfigurer

博客介绍了一种特殊化实现工具,用于解析定义中属性值和注解值,属性来源为当前对象及设置给自己的对象。在特定版本中缺省使用该工具替换了其他工具,还提及了继承关系、使用示例,给出了Spring Context 5.1.5.RELEASE版本的源代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

介绍

PropertySourcesPlaceholderConfigurerPlaceholderConfigurerSupport的特殊化实现。它用于解析bean定义中的属性值,以及注解@Value的值,使用的属性来源是当前的Spring Environment对象,以及设置给自己的PropertySources对象。

Spring Context 3.1 XSD或者更高版本中,缺省使用该工具替换了PlaceholderConfigurerSupport,而<=3.0较老的Spring Context XSD中,为了保持和之前的版本兼容,缺省还是使用PropertyPlaceholderConfigurer

继承关系

PropertySourcesPlaceholderConfigurer

使用


// Spring Boot 自动配置类 PropertyPlaceholderAutoConfiguration
@Configuration
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
public class PropertyPlaceholderAutoConfiguration {

	@Bean
	@ConditionalOnMissingBean(search = SearchStrategy.CURRENT)
	public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
		return new PropertySourcesPlaceholderConfigurer();
	}

}

以上例子PropertyPlaceholderAutoConfiguration定义一个PropertySourcesPlaceholderConfigurer bean,该bean作为一个BeanFactoryPostProcessor,会在容器启动时容器后置处理阶段执行自己的任务。

源代码

源代码版本 Spring Context 5.1.5.RELEASE

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.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringValueResolver;


public class PropertySourcesPlaceholderConfigurer extends PlaceholderConfigurerSupport 
	implements EnvironmentAware {

	/**
	 *  the name given to the PropertySource for the set of
	 * #mergeProperties() merged properties supplied to this configurer.
	 */
	public static final String LOCAL_PROPERTIES_PROPERTY_SOURCE_NAME = "localProperties";

	/**
	 * the name given to the PropertySource that wraps the
	 *#setEnvironment environment supplied to this configurer.
	 */
	public static final String ENVIRONMENT_PROPERTIES_PROPERTY_SOURCE_NAME = "environmentProperties";


	@Nullable
	private MutablePropertySources propertySources;

	@Nullable
	private PropertySources appliedPropertySources;

	@Nullable
	private Environment environment;


	/**
	 * Customize the set of 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);
	}

	/**
	 * PropertySources from the given Environment
	 * will be searched when replacing ${...} placeholders.
	 * @see #setPropertySources
	 * @see #postProcessBeanFactory
	 */
	@Override
	public void setEnvironment(Environment environment) {
		this.environment = environment;
	}


	/**
	 * Processing occurs by replacing ${...} placeholders in bean definitions by resolving each
	 * against this configurer's set of PropertySources, which includes:
	 * 
	 * 1. all org.springframework.core.env.ConfigurableEnvironment#getPropertySources
	 * environment property sources, if an Environment #setEnvironment is present
	 *
	 * 2. #mergeProperties merged local properties, if #setLocation any
	 * #setLocations have #setProperties been
	 * #setPropertiesArray specified
	 *
	 * 3. any property sources set by calling #setPropertySources
	 * 
	 * If #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.
	 */
     
    // 这是接口  BeanFactoryPostProcessor 约定的方法,会在容器启动过程中的后置处理阶段被调用
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		if (this.propertySources == null) {
        // 如果外部指定了 this.propertySources, 则直接使用它,否则
        // 从当前 Spring 的 Environment 对象和自身的 #mergeProperties 方法调用返回的 Properties 对象构建属性源
        // 对象 this.propertySources
			this.propertySources = new MutablePropertySources();
			if (this.environment != null) {
				this.propertySources.addLast(
					new PropertySource<Environment>(ENVIRONMENT_PROPERTIES_PROPERTY_SOURCE_NAME, 
						this.environment) {
						@Override
						@Nullable
						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);
			}
		}

       // 构造一个基于特定属性源 this.propertySources 对属性值进行解析的属性值解析器 
       // PropertySourcesPropertyResolver, 对容器中所有的 bean 定义中的属性值,构造函数参数值,
       // @Value 注解值进行属性占位符解析和替换
		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);


       // 结合属性 this. ignoreUnresolvablePlaceholders 对 propertyResolver 作进一步封装,
       // 封装出来一个 StringValueResolver valueResolver,这是最终要应用的属性值解析器
		StringValueResolver valueResolver = strVal -> {
			String resolved = (this.ignoreUnresolvablePlaceholders ?
					propertyResolver.resolvePlaceholders(strVal) :
					propertyResolver.resolveRequiredPlaceholders(strVal));
			if (this.trimValues) {
				resolved = resolved.trim();
			}
			return (resolved.equals(this.nullValue) ? null : resolved);
		};

       // 调用基类  PlaceholderConfigurerSupport 实现的对容器中所有 bean定义进行遍历处理属性值中占位符解析
       // 的逻辑
		doProcessProperties(beanFactoryToProcess, valueResolver);
	}

	/**
	 * 该方法是基类定义的方法,这里的实现直接抛出了异常,因为该实现类实际上使用了另外一个 processProperties
     * 方法实现
     * Implemented for compatibility with
	 * org.springframework.beans.factory.config.PlaceholderConfigurerSupport.
	 * @deprecated in favor of
	 * #processProperties(ConfigurableListableBeanFactory, ConfigurablePropertyResolver)
	 * @throws UnsupportedOperationException in this implementation
	 */
	@Override
	@Deprecated
	protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props) {
		throw new UnsupportedOperationException(
			"Call processProperties(ConfigurableListableBeanFactory, ConfigurablePropertyResolver) instead");
	}

	/**
	 * Return the property sources that were actually applied during
	 * #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 yet been applied");
		return this.appliedPropertySources;
	}

}

参考文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值