概述
介绍
PlaceholderConfigurerSupport是Spring提供的一个工具类,用于解析bean定义中属性值里面的占位符,这是一个抽象类,不能被直接实例化使用。
PlaceholderConfigurerSupport继承自PropertyResourceConfigurer,而PropertyResourceConfigurer具备如下能力 :
- 指定属性源;
Properties对象形式指定的本地属性源,- 需要从文件路径中加载的外部属性源
- 合并属性源中的属性;
- 对
bean工厂(可以直接理解为IoC容器)做某种处理 - 实现了接口
BeanFactoryPostProcessor,可以在容器后置处理阶段做些事情
PlaceholderConfigurerSupport在PropertyResourceConfigurer的基础上对上面第三点提到的"某种处理"做出了明确实现,也就是替换所有bean定义中属性值和构造函数参数值中的特定格式的属性占位符。
围绕自己的占位符属性替换逻辑,PlaceholderConfigurerSupport提供了相应的占位符格式设置功能,解析过程中的一些规则的开关功能。具体如下:
-
占位符格式设置功能 :
- 设置占位符前缀,缺省为
${ - 设置占位符后缀,缺省为
} - 设置占位符缺省值分隔符,缺省为
:
缺省情况下,也就是会处理如下格式的占位符 :
@Value("${person.age}")<property name="driverClassName" value="${driver}"/><property name="url" value="jdbc:${dbname:defaultdb}"/>
- 设置占位符前缀,缺省为
-
解析规则设置功能 :
- 是否修剪值前后的空白,
缺省为 : 不修剪值前后的空白
- 遇到不可解析的占位符时是否抛出异常
缺省为 : 遇到不可解析的占位符时抛出异常
BeanDefinitionStoreException
- 是否修剪值前后的空白,
PlaceholderConfigurerSupport的方法#doProcessProperties是其核心逻辑,该方法对容器中除了自己(PlaceholderConfigurerSupport bean自己)之外的所有bean定义中的属性值,构造函数参数值进行了属性占位符到相应属性值的解析和替换。
PlaceholderConfigurerSupport自身并没有实现基类PropertyResourceConfigurer定义的抽象方法abstract void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props),该方法的真正目的才是基于指定属性源对容器进行某种操作,该方法留给PlaceholderConfigurerSupport的实现子类使用,具体的可以参考Spring对PlaceholderConfigurerSupport的内置实现子类PropertySourcesPlaceholderConfigurer,PropertySourcesPlaceholderConfigurer正是实现了该方法,基于指定的属性源,在其中使用PlaceholderConfigurerSupport提供的方法#doProcessProperties进行了所定义的处理逻辑。
跟
PlaceholderConfigurerSupport类似的另外一个属性值解析工具是PropertyOverrideConfigurer。PlaceholderConfigurerSupport是分析每个bean定义内属性值中的占位符将它们替换成相应的属性值,而PropertyOverrideConfigurer则是解析和处理所有类似beanName.property=value这种格式的属性设置。
继承关系

源代码
源代码版本 : Spring Beans 5.1.5.RELEASE
package org.springframework.beans.factory.config;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.lang.Nullable;
import org.springframework.util.StringValueResolver;
public abstract class PlaceholderConfigurerSupport extends PropertyResourceConfigurer
implements BeanNameAware, BeanFactoryAware {
/** Default placeholder prefix: ${ */
public static final String DEFAULT_PLACEHOLDER_PREFIX = "${";
/** Default placeholder suffix: } */
public static final String DEFAULT_PLACEHOLDER_SUFFIX = "}";
/** Default value separator: : */
public static final String DEFAULT_VALUE_SEPARATOR = ":";
/** Defaults to #DEFAULT_PLACEHOLDER_PREFIX. */
protected String placeholderPrefix = DEFAULT_PLACEHOLDER_PREFIX;
/** Defaults to #DEFAULT_PLACEHOLDER_SUFFIX. */
protected String placeholderSuffix = DEFAULT_PLACEHOLDER_SUFFIX;
/** Defaults to #DEFAULT_VALUE_SEPARATOR. */
@Nullable
protected String valueSeparator = DEFAULT_VALUE_SEPARATOR;
protected boolean trimValues = false;
@Nullable
protected String nullValue;
protected boolean ignoreUnresolvablePlaceholders = false;
@Nullable
private String beanName;
@Nullable
private BeanFactory beanFactory;
/**
* Set the prefix that a placeholder string starts with.
* The default is #DEFAULT_PLACEHOLDER_PREFIX.
*/
public void setPlaceholderPrefix(String placeholderPrefix) {
this.placeholderPrefix = placeholderPrefix;
}
/**
* Set the suffix that a placeholder string ends with.
* The default is #DEFAULT_PLACEHOLDER_SUFFIX.
*/
public void setPlaceholderSuffix(String placeholderSuffix) {
this.placeholderSuffix = placeholderSuffix;
}
/**
* Specify the separating character between the placeholder variable
* and the associated default value, or null if no such
* special character should be processed as a value separator.
* The default is #DEFAULT_VALUE_SEPARATOR.
*/
public void setValueSeparator(@Nullable String valueSeparator) {
this.valueSeparator = valueSeparator;
}
/**
* Specify whether to trim resolved values before applying them,
* removing superfluous whitespace from the beginning and end.
* Default is false.
* @since 4.3
*/
public void setTrimValues(boolean trimValues) {
this.trimValues = trimValues;
}
/**
* Set a value that should be treated as null when resolved
* as a placeholder value: e.g. "" (empty String) or "null".
* Note that this will only apply to full property values,
* not to parts of concatenated values.
*
* By default, no such null value is defined. This means that
* there is no way to express null as a property value
* unless you explicitly map a corresponding value here.
*/
public void setNullValue(String nullValue) {
this.nullValue = nullValue;
}
/**
* Set whether to ignore unresolvable placeholders.
* Default is "false": An exception will be thrown if a placeholder fails
* to resolve. Switch this flag to "true" in order to preserve the placeholder
* String as-is in such a case, leaving it up to other placeholder configurers
* to resolve it.
*/
public void setIgnoreUnresolvablePlaceholders(boolean ignoreUnresolvablePlaceholders) {
this.ignoreUnresolvablePlaceholders = ignoreUnresolvablePlaceholders;
}
/**
* Only necessary to check that we're not parsing our own bean definition,
* to avoid failing on unresolvable placeholders in properties file locations.
* The latter case can happen with placeholders for system properties in
* resource locations.
* @see #setLocations
* @see org.springframework.core.io.ResourceEditor
*/
@Override
public void setBeanName(String beanName) {
this.beanName = beanName;
}
/**
* Only necessary to check that we're not parsing our own bean definition,
* to avoid failing on unresolvable placeholders in properties file locations.
* The latter case can happen with placeholders for system properties in
* resource locations.
* @see #setLocations
* @see org.springframework.core.io.ResourceEditor
*/
@Override
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
// 该方法是 PlaceholderConfigurerSupport 对容器中所有 bean 定义进行处理的核心逻辑方法,
// 该方法留给具体实现子类使用,当然具体实现子类也可以重写该方法或者不使用该方法。
//
// Spring 提供的 PlaceholderConfigurerSupport 具体实现子类 PropertyPlaceholderConfigurer
// 直接使用了该方法。
protected void doProcessProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
StringValueResolver valueResolver) {
// BeanDefinitionVisitor 是一个专门为 PropertyPlaceholderConfigurer 设计的 bean 定义
// 访问器,主要是遍历 bean 定义中的属性值和构造函数参数值字符串,使用 valueResolver
// 解析相应值字符串中的占位符,结合给定的属性源,将占位符其替换为相应的属性值
BeanDefinitionVisitor visitor = new BeanDefinitionVisitor(valueResolver);
// 获取容器中所有的 bean 名称,这样可以访问到容器中所有的 bean 定义
String[] beanNames = beanFactoryToProcess.getBeanDefinitionNames();
for (String curName : beanNames) {
// Check that we're not parsing our own bean definition,
// to avoid failing on unresolvable placeholders in properties file locations.
// this.beanName 记录了当前对象,也就是当前 PlaceholderConfigurerSupport 对象的
// bean 名称,这里的 for 循环会使用 visitor 处理处理当前 PlaceholderConfigurerSupport 对象
// 之外的所有 bean 定义
if (!(curName.equals(this.beanName) && beanFactoryToProcess.equals(this.beanFactory))) {
BeanDefinition bd = beanFactoryToProcess.getBeanDefinition(curName);
try {
visitor.visitBeanDefinition(bd);
}
catch (Exception ex) {
throw new BeanDefinitionStoreException(bd.getResourceDescription(),
curName, ex.getMessage(), ex);
}
}
}
// New in Spring 2.5: resolve placeholders in alias target names and aliases as well.
// bean 的别名,以及别名的目标bean名称中也可能使用占位符,这里也做处理
beanFactoryToProcess.resolveAliases(valueResolver);
// New in Spring 3.0: resolve placeholders in embedded values such as annotation attributes.
// 将这里所使用的值解析器 valueResolver 添加到容器,用于处理类似注解属性中的嵌入值。
beanFactoryToProcess.addEmbeddedValueResolver(valueResolver);
}
}
本文介绍了一个用于解析定义中属性值占位符的抽象工具类。它继承自特定类,具备指定属性源、合并属性等能力,实现了相关接口。围绕占位符属性替换逻辑,提供格式设置和规则开关功能,核心方法可进行占位符解析替换,还提及类似工具。
5857

被折叠的 条评论
为什么被折叠?



