applyMergedBeanDefinitionPostProcessors方法
在bean的生命周期中,第三次后置处理器调用使用了MergedBeanDefinition
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);,应用合并BeanDefinition的后置处理器此方法主要缓存一些带了注解的属性字段例如@Autowired、@Common等元数据注入信息
示例代码
package com.mergebd;
@Component
public class A {
}
package com.mergebd;
public class ChildBean {
@Autowired
A a;
private String contry;
private String city;
public String getContry() {
return contry;
}
public void setContry(String contry) {
this.contry = contry;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
public String toString() {
return "contry="+contry+" city="+city;
}
}
package com.mergebd;
public class RootBean {
private String contry;
private String city;
public String getContry() {
return contry;
}
public void setContry(String contry) {
this.contry = contry;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
public String toString() {
return "contry="+contry+" city="+city;
}
}
package com.mergebd;
@Configuration
@ComponentScan("com.mergebd")
public class MergeAppConfig {
public static void main(String[] args) {
AnnotationConfigApplicationContext ac =
new AnnotationConfigApplicationContext();
ac.register( MergeAppConfig.class );
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition( );
rootBeanDefinition.setBeanClass( RootBean.class);
rootBeanDefinition.getPropertyValues().add( "contry","zh" );
rootBeanDefinition.getPropertyValues().add( "city","beijing" );
ac.registerBeanDefinition( "root",rootBeanDefinition );
GenericBeanDefinition genericBeanDefinition =new GenericBeanDefinition( );
genericBeanDefinition .setBeanClass( ChildBean.class);
genericBeanDefinition.setParentName( "root" );
genericBeanDefinition.getPropertyValues().add( "city","shenzhen" );
ac.registerBeanDefinition( "child",genericBeanDefinition );
ac.refresh();
System.out.println( ac.getBean( "child" ).toString() );
}
}
degub分析结果
applyMergedBeanDefinitionPostProcessors方法

由于BeanDefinition有各种实现类,且实现类能指定'父子'依赖信息的关系(不是继承关系,仅仅是指定数据的父子关系)。如果元数据依赖不合并的话,则这个beanDefinition的元数据信息将不完整。
合并的BeanDefinition测试结果
ChildBean并没有赋值contry属性,返回结果含contry是zh,city是shenzhen。说明了进行Merge合并

调用链
AbstractApplicationContext#refresh
AbstractApplicationContext#invokeBeanFactoryPostProcessors
PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory, List<BeanFactoryPostProcessor>)
DefaultListableBeanFactory#getBeanNamesForType(Class<?>, boolean, boolean)
DefaultListableBeanFactory#doGetBeanNamesForType
debug分析
doGetBeanNamesForType
根据beanDefinitionNames遍历所有

getMergedLocalBeanDefinition
mergedBeanDefinitions集合在当前BeanName第一次调用到这里肯定为null

getMergedBeanDefinition

getParentName
mergedBeanDefinitions经过以上步骤,这里也是null。然后判断当前BeanDefinition的ParentName是否为null

parentName
获取parentName的BeanDefinition

getMergedBeanDefinitionpbd
parentName也经过getMergedBeanDefinitionpbd方法判断是否具有parentName属性

override
以parentBeanDefinition作为基准,子BeanDefinition复制到parentBeanDefinition

setBeanClass设置Bean类

setPropertyValues设置属性值

PropertyValues属性值覆盖

经过一系列其他的BeanDefinition的属性值赋值给父BeanDefinition,最终把这个父BeanDefinition用put到mergedBeanDefinitions,完成了child此时的属性合并(此时的BeanDefinition不一定是最终的,当然在示例代码是最终的)
其他地方调用getMergedLocalBeanDefinition方法
preInstantiateSingletons
DefaultListableBeanFactory#preInstantiateSingletons在准备实例化单例对象,经过遍历BeanNames会从mergedBeanDefinitions(此时应该不会为null)获取合成的BeanDefinition

createBean
在创建Bean之前,清除合成BeanDefinition集合。需要重新获取
执行到AbstractBeanFactory#doGetBean
typeCheckOnly默认是false

clearMergedBeanDefinition
从mergedBeanDefinitions集合remove当前beanName。并添加到alreadyCreated正在创建集合中。之后再次调用getMergedLocalBeanDefinition方法,重新获取一遍合成BeanDefinition

总结:
由于BeanDefinition的实现子类可以指定“父子关系”。MergedBeanDefinition就是表示如何正确获取合成BeanDefinition属性值
关键点:
1、getMergedLocalBeanDefinition方法执行时机
2、mergedBeanDefinitions集合
后置处理器方法applyMergedBeanDefinitionPostProcessors 的BeanDefinition都是MergedBeanDefinition(合成的) 作用是缓存注解信息
网友评论