三十三、IOC之深入分析 PropertyOverrideConfigurer

IOC之深入分析 PropertyOverrideConfigurer

BeanFactoryPostProcessor 作用于 BeanDefinition 完成加载之后与 Bean 实例化之前,是 Spring 提供的一种强大的扩展机制。它有两个重要的子类,一个是 PropertyPlaceholderConfigurer,另一个是 PropertyOverrideConfigurer ,其中 PropertyPlaceholderConfigurer 允许我们通过配置 Properties 的方式来取代 Bean 中定义的占位符,PropertyOverrideConfigurer 允许我们对 Spring 容器中配置的任何我们想处理的 bean 定义的 property 信息进行覆盖替换。

原理

UML图:

propertyOverrideConfigurer结构图

与 PropertyPlaceholderConfigurer 一样,也是继承 PropertyResourceConfigurer,我们知道 PropertyResourceConfigurer 对 BeanFactoryPostProcessor 的 postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) 方法提供了实现,在该实现中它会去读取指定配置文件中的内容,然后调用 processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props) 方法。该方法是一个抽象方法,具体的实现由子类来实现,所以这里我们只需要看 PropertyOverrideConfigurer 中 processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props) 方法的具体实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// PropertyOverrideConfigurer.java
@Override
protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props)
throws BeansException {

// 迭代配置文件中的内容
for (Enumeration<?> names = props.propertyNames(); names.hasMoreElements();) {
String key = (String) names.nextElement();
try {
processKey(beanFactory, key, props.getProperty(key));
}
catch (BeansException ex) {
String msg = "Could not process key '" + key + "' in PropertyOverrideConfigurer";
if (!this.ignoreInvalidKeys) {
throw new BeanInitializationException(msg, ex);
}
if (logger.isDebugEnabled()) {
logger.debug(msg, ex);
}
}
}
}

迭代 props 数组,依次调用 processKey(ConfigurableListableBeanFactory factory, String key, String value) 方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// PropertyOverrideConfigurer.java

/**
* Bean 名字的分隔符
*/
public static final String DEFAULT_BEAN_NAME_SEPARATOR = ".";
private String beanNameSeparator = DEFAULT_BEAN_NAME_SEPARATOR;

protected void processKey(ConfigurableListableBeanFactory factory, String key, String value) throws BeansException {

// 判断是否存在 ".",即获取其索引位置
int separatorIndex = key.indexOf(this.beanNameSeparator);
if (separatorIndex == -1) {
throw new BeanInitializationException("Invalid key '" + key +
"': expected 'beanName" + this.beanNameSeparator + "property'");
}
// 得到 beanName
String beanName = key.substring(0, separatorIndex);
// 得到属性名
String beanProperty = key.substring(separatorIndex + 1);
this.beanNames.add(beanName);
// 替换
applyPropertyValue(factory, beanName, beanProperty, value);
if (logger.isDebugEnabled()) {
logger.debug("Property '" + key + "' set to value [" + value + "]");
}
}

获取分割符 “.” 的索引位置,得到 beanName 以及相应的属性,然后调用 applyPropertyValue(ConfigurableListableBeanFactory factory, String beanName, String property, String value) 方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// PropertyOverrideConfigurer.java
protected void applyPropertyValue(ConfigurableListableBeanFactory factory, String beanName, String property, String value) {

// 获得 BeanDefinition 对象
BeanDefinition bd = factory.getBeanDefinition(beanName);
BeanDefinition bdToUse = bd;
while (bd != null) {
bdToUse = bd;
bd = bd.getOriginatingBeanDefinition();
}
// 设置 PropertyValue 到 BeanDefinition 中
PropertyValue pv = new PropertyValue(property, value);
pv.setOptional(this.ignoreInvalidKeys);
bdToUse.getPropertyValues().addPropertyValue(pv);
}

从容器中获取 BeanDefinition ,然后根据属性 property 和其值 value 构造成一个 PropertyValue 对象,最后调用 addPropertyValue(PropertyValue pv ) 方法。PropertyValue 是用于保存一组bean属性的信息和值的对像:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// MutablePropertyValues.java
public MutablePropertyValues addPropertyValue(PropertyValue pv) {
for (int i = 0; i < this.propertyValueList.size(); i++) {
PropertyValue currentPv = this.propertyValueList.get(i);
// 匹配
if (currentPv.getName().equals(pv.getName())) {
// 合并属性
pv = mergeIfRequired(pv, currentPv);
// 覆盖属性
setPropertyValueAt(pv, i);
return this;
}
}
// 未匹配到,添加到 propertyValueList 中
this.propertyValueList.add(pv);
return this;
}

添加 PropertyValue 对象,替换或者合并相同的属性值。

propertyOverride和PropertyPlaceholder

propertyOverride和PropertyPlaceholder


三十三、IOC之深入分析 PropertyOverrideConfigurer
http://www.muzili.ren/2022/06/11/IOC之深入分析 PropertyOverrideConfigurer/
作者
jievhaha
发布于
2022年6月11日
许可协议