IOC之深入分析 PropertyOverrideConfigurer
BeanFactoryPostProcessor 作用于 BeanDefinition 完成加载之后与 Bean 实例化之前,是 Spring 提供的一种强大的扩展机制。它有两个重要的子类,一个是 PropertyPlaceholderConfigurer,另一个是 PropertyOverrideConfigurer ,其中 PropertyPlaceholderConfigurer 允许我们通过配置 Properties 的方式来取代 Bean 中定义的占位符,PropertyOverrideConfigurer 允许我们对 Spring 容器中配置的任何我们想处理的 bean 定义的 property 信息进行覆盖替换。
原理
UML图:
与 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
| @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
|
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'"); } 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
| protected void applyPropertyValue(ConfigurableListableBeanFactory factory, String beanName, String property, String value) {
BeanDefinition bd = factory.getBeanDefinition(beanName); BeanDefinition bdToUse = bd; while (bd != null) { bdToUse = bd; bd = bd.getOriginatingBeanDefinition(); } 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
| 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; } } this.propertyValueList.add(pv); return this; }
|
添加 PropertyValue 对象,替换或者合并相同的属性值。
propertyOverride和PropertyPlaceholder