spring之PropertyOverrideConfigurer源码解析
PropertyOverrideConfigurer的介绍
上一篇博客spring之PropertyPlaceholderConfigurer源码解析中,介绍了BeanFactoryPostProcessor的一个应用例子PropertyPlaceholderConfigurer,这篇博客将介绍BeanFactoryPostProcessor的另外一个应用例子PropertyOverrideConfigurer。PropertyOverrideConfigurer的使用场景是,允许我们直接在properties文件中通过配置"bean.属性名称=属性值"的方式直接替换bean的属性值。
PropertyOverrideConfigurer的类结构
与上一篇博客分析的PropertyPlaceholderConfigurer的类结构类似,一样是继承了PropertyResourceConfigurer。
源码解析
PropertyResourceConfigurer实现BeanFactoryPostProcessor接口源码
由于与PropertyPlaceholderConfigurer一样是继承PropertyResourceConfigurer,这里我们再贴一下PropertyResourceConfigurer源码
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
try {
Properties mergedProps = mergeProperties();
//获取所有properties并合并转换
// Convert the merged properties, if necessary.
convertProperties(mergedProps);
// Let the subclass process the properties.
//主要过程还是调用子类的processProperties
processProperties(beanFactory, mergedProps);
}
catch (IOException ex) {
throw new BeanInitializationException("Could not load properties", ex);
}
}
PropertyOverrideConfigurer的processProperties方法源码
@Override
protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props)
throws BeansException {
//遍历所有的配置文件的属性名
for (Enumeration<?> names = props.propertyNames(); names.hasMoreElements();) {
String key = (String) names.nextElement();
try {
//执行processKey方法
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);
}
}
}
}
//分析processKey方法
protected void processKey(ConfigurableListableBeanFactory factory, String key, String value)
throws BeansException {
//获取properties中属性名中字符“.”第一次出现的位置
int separatorIndex = key.indexOf(this.beanNameSeparator);
if (separatorIndex == -1) {
//若properties中属性名不存在“.”,则不符合配置规则,抛出异常
throw new BeanInitializationException("Invalid key '" + key +
"': expected 'beanName" + this.beanNameSeparator + "property'");
}
//获取第一次字符“.”前面的串作为beanName
String beanName = key.substring(0, separatorIndex);
//后面的串作为beanProperty,作为applyPropertyValue方法的入参
String beanProperty = key.substring(separatorIndex + 1);
this.beanNames.add(beanName);
//调用applyPropertyValue方法
applyPropertyValue(factory, beanName, beanProperty, value);
if (logger.isDebugEnabled()) {
logger.debug("Property '" + key + "' set to value [" + value + "]");
}
}
//分析applyPropertyValue方法
protected void applyPropertyValue(
ConfigurableListableBeanFactory factory, String beanName, String property, String value) {
//先根据前面解析出来的beanName获取BeanDefinition
BeanDefinition bd = factory.getBeanDefinition(beanName);
//将bd复制给bdToUse
BeanDefinition bdToUse = bd;
while (bd != null) {
bdToUse = bd;
bd = bd.getOriginatingBeanDefinition();
}
//构造一对pv PropertyValue
PropertyValue pv = new PropertyValue(property, value);
pv.setOptional(this.ignoreInvalidKeys);
//并调用MutablePropertyValues的addPropertyValue方法
bdToUse.getPropertyValues().addPropertyValue(pv);
}
MutablePropertyValues.addPropertyValue源码
public MutablePropertyValues addPropertyValue(PropertyValue pv) {
for (int i = 0; i < this.propertyValueList.size(); i++) {
//遍历已有的pv,拿到相同的属性名之后,检查并替换值
PropertyValue currentPv = this.propertyValueList.get(i);
if (currentPv.getName().equals(pv.getName())) {
pv = mergeIfRequired(pv, currentPv);
setPropertyValueAt(pv, i);
return this;
}
}
this.propertyValueList.add(pv);
return this;
}