MergedBeanDefinition分析
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方法
applyMergedBeanDefinitionPostProcessors.png
由于BeanDefinition有各种实现类,且实现类能指定'父子'依赖信息的关系(不是继承关系,仅仅是指定数据的父子关系)。如果元数据依赖不合并的话,则这个beanDefinition的元数据信息将不完整。
合并的BeanDefinition测试结果
ChildBean并没有赋值contry属性,返回结果含contry是zh,city是shenzhen。说明了进行Merge合并
merge.png
调用链
AbstractApplicationContext#refresh
AbstractApplicationContext#invokeBeanFactoryPostProcessors
PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory, List<BeanFactoryPostProcessor>)
DefaultListableBeanFactory#getBeanNamesForType(Class<?>, boolean, boolean)
DefaultListableBeanFactory#doGetBeanNamesForType
debug分析
doGetBeanNamesForType
根据beanDefinitionNames遍历所有
doGetBeanNamesForType.png
getMergedLocalBeanDefinition
mergedBeanDefinitions集合在当前BeanName第一次调用到这里肯定为null
getMergedLocalBeanDefinition.png
getMergedBeanDefinition
getMergedBeanDefinition.pnggetParentName
mergedBeanDefinitions经过以上步骤,这里也是null。然后判断当前BeanDefinition的ParentName是否为null
getParentName.png
parentName
获取parentName的BeanDefinition
parentName.png
getMergedBeanDefinitionpbd
parentName也经过getMergedBeanDefinitionpbd方法判断是否具有parentName属性
getMergedBeanDefinitionpbd.png
override
以parentBeanDefinition作为基准,子BeanDefinition复制到parentBeanDefinition
deepcopy.png
setBeanClass设置Bean类
setBeanClass.pngsetPropertyValues设置属性值
setPropertyValues.pngPropertyValues属性值覆盖
copyvalues.png经过一系列其他的BeanDefinition的属性值赋值给父BeanDefinition,最终把这个父BeanDefinition用put到mergedBeanDefinitions,完成了child此时的属性合并(此时的BeanDefinition不一定是最终的,当然在示例代码是最终的)
其他地方调用getMergedLocalBeanDefinition方法
preInstantiateSingletons
DefaultListableBeanFactory#preInstantiateSingletons在准备实例化单例对象,经过遍历BeanNames会从mergedBeanDefinitions(此时应该不会为null)获取合成的BeanDefinition
preInstantiateSingletons.png
createBean
在创建Bean之前,清除合成BeanDefinition集合。需要重新获取
执行到AbstractBeanFactory#doGetBean
typeCheckOnly默认是false
markBeanAsCreated.png
clearMergedBeanDefinition
从mergedBeanDefinitions集合remove当前beanName。并添加到alreadyCreated正在创建集合中。之后再次调用getMergedLocalBeanDefinition方法,重新获取一遍合成BeanDefinition
clearMergedBeanDefinition.png
总结:
由于BeanDefinition的实现子类可以指定“父子关系”。MergedBeanDefinition就是表示如何正确获取合成BeanDefinition属性值
关键点:
1、getMergedLocalBeanDefinition方法执行时机
2、mergedBeanDefinitions集合
后置处理器方法applyMergedBeanDefinitionPostProcessors 的BeanDefinition都是MergedBeanDefinition(合成的) 作用是缓存注解信息