前言
之前读spring源码,以为Bean定义保存在beanFactory的beanDefinitionMap中,创建时获取bean定义,根据定义创建bean,简单明了
而最近调试发现,mergedBeanDefinitions中也存储了一份bean定义,而且创建时实际是从这个map中获取
于是对mergedBeanDefinition(合并bean定义)产生了好奇,决定看一看到底什么是合并bean定义
先说结论:
mergedBeanDefinition是为了实现bean定义继承,但感觉有点鸡肋,xml配置可以通过parent来实现,注解方式基本不再支持bean定义的继承了
所以说这篇文章也只是简单记录一下,免得mergedBeanDefinition总是干扰源码的阅读
BeanDefinition的继承
bean定义就是bean的图纸,可以配置一些属性,比如是否懒加载,是否单例等
假如现在有了A的bean定义,而B的bean定义和A的属性基本差不多,只是个别不属性太一样,那就可以让B继承A,这样可以减轻B的定义配置,就类似JAVA的继承
xml
早起都用XML配置bean定义,可以类似使用如下配置完成bean定义的继承
<bean id="A" class="com.xxx.A" lazy-init="true"></bean>
<bean id="B" class="com.xxx.B" parent="A"/> // 指定parent属性继承
实际上好像比这个复杂,但没啥意义不研究了
这样A配置了懒加载,B没有配置,就会继承懒加载的属性
这种情况下
- (B) beanDefinitionMap存放原本的B的bean定义,而mergedBeanDefinitions存储的B是B与A合并之后的新bean
定义 - (A) beanDefinitionMap存放原本的A的bean定义,而mergedBeanDefinitions存储的是原本A bean定义的clone
示意图如下
这样不管存不存在合并,mergedBeanDefinitions存放的都是最终创建bean所参考的bean定义
注解
现在都不怎么用XML,都是用注解扫描自动生成bean,我大概看了一下好像没有parent相关的注解,猜测可能是这个功能太鸡肋,注解方式不提供了
而注解扫描出来的bean定义,就和上面的A一样,由于没有parent,所以在mergedBeanDefinitions只是存了份clone(如果不是RootBeanDefinition转化为RootBeanDefinition,和clone差不多)
相关代码
其中合并bean定义方法即为
overrideFrom
总结
MergedBeanDefinition的研究只是为了扫清阅读源码障碍,实际作用不大
我测试了一下,我们一个开发一年左右的代码,运行并没有进入overrideFrom
方法,也就是说不光我们写的代码没用bean定义继承,第三方依赖工具也没有
私以为spring还保留着MergedBeanDefinition只是为了兼容原xml配置bean(可能也有其使用场景我不知道),而它的主要功能已经不是合并bean定义,而是把不同类型的bean定义转换为RootBeanDefinition,字面上理解为合并也可以
总之,bean定义在DefaultListableBeanFactory(springboot的beanFactory)会存储两份,一般mergedBeanDefinitions存储的是beanDefinitionMap的clone或者转换为RootBeanDefinition,实际创建bean参考的是mergedBeanDefinitions中的RootBean定义