合并BeanDefinition

在这里插入图片描述
一开始 mergedBeanDefinitions缓存里是没有的,它会执行getMergedBeanDefinition
在这里插入图片描述
从上面可看到,默认containingBd为null,暂时还不知道containingBd的应用场景。

AbstractBeanFactory#getMergedBeanDefinition(String, BeanDefinition, BeanDefinition)

一个重要的概念:RootBeanDefinition的stale属性,合并BeanDefinition的意义在于

  • 对ParentBeanDefinition的合并,如果
    在这里插入图片描述
    在这里插入图片描述

合并BeanDefinition原理

官方

Spring

Spring通过Bean替代了传统类和对象的构建,但也继承了OOP的一些思想。BeanDefinition就具有继承的思想,这是一种非常有效的方式。
在这里插入图片描述

在这里插入图片描述

相关组件
  • RootBeanDefinition
  • mergedBeanDefinitions缓存
    在这里插入图片描述
    可以这样理解,一般我们通过用户各种定义的信息获得不同类型的BeanDefinition,之后通过合并得到RootBeanDefinition放入缓存。RootBeanDefinition是在对Bean的处理过程中指定需要的BeanDefinition,你可以理解为合格的、完整的BeanDefinition,其他的BeanDefinition最终只有通过合并成为RootBeanDefinition才可以说完整代表一个Bean的所有信息,不然都是中间品。

为什么这么说?
一般这样理解,查看BeanDefinition的体系,BeanDefinition作为接口定义了BeanDefinition的一些规范,而AbstractBeanDefinition增强实现了一些方法,作为复用实现,这两个都不会是真正在交互中使用的BeanDefinition对象,剩下的GenericBeanDefinition代表常规方式建立的BeanDefinition,AnnotatedBeanDefinition具有Annotated前缀表名通过一般注解得来的BeanDefinition,只有RootBeanDefinition才是真正意义上的BeanDefinition对象,这样由结果得到原因的解释有点废话,但是也是具有帮助的,BeanDefinition作为信息集合体,并且具有多种渠道转化而来,这就导致它会有功能组件(Generic-、Annotated-、Child-)和集合体代表组件(RootBeanDefinition),最终交互当然是要通过RootBeanDefinition来实现
在这里插入图片描述>

示例

以这位博主的博客为例
Spring合并BeanDefinition的原理
在这里插入图片描述
以ChildBean类为目标来分析一下

第一次合并 —— mergedBeanDefinitions缓存为空的情况

第一次合并一般并非在实例化该Bean的过程中。比如在示例中是在从BeanDefinitionMap中找BeanDefinitionPostProcessor的过程中遍历所有的BeanDefinition
在这里插入图片描述
遍历的时候会对每个BeanDefinition作判断,这时候就需要用到RootBeanDefinition这个代表组件。
在这里插入图片描述
先通过合并拿到RootBeanDefinition,这就是第一次合并在这里插入图片描述
此时是mbd为null的场景,并且mbd确实有parentBeanDefinition。

在这里插入图片描述
这其中又加了一个判断parentBeanName是不是和当前Beanname相同的逻辑。这里当然不同,pbd就是父BeanDefinition(RootBeanDefinition类型)

AbstractBeanFactory#getMergedBeanDefinition(String)

在这里插入图片描述
以父类为入参构造新的RootBeanDefinition
在这里插入图片描述

这步看起来有些黑人问号,为什么不直接把pbd赋值给mbd呢,通过new方式两个RootBeanDefinition完全一模一样。
此时再讲childBean的BeanDefinition更新到mbd中,这样就完成对于父BeanDefinition和子BeanDefinition的合并,这也是合并BeanDefinition的主要目的
合并的过程,把实例中的更新操作放到这里了,这时的更新后的ChildBean的RootBeanDefinition已经好了
AbstractBeanDefinition#overrideFrom

第二次合并 —— doGetBean 创建Bean实例时

在第一次创建好ChildBean的RootBeanDefinition时,它是新鲜的,stale为false(stale本意不新鲜的)
在这里插入图片描述
并且在之后的几次使用中都是新鲜的,那从哪里开始stale为会变为true呢?

在这里插入图片描述

首先我们知道了RootBeanDefinition的两个用途:

  1. 用作对Bean的判断,比如我们上面对判断Bean是否抽象类或者其他都是要用该Bean的RootBeanDefinition对象来做判断
  2. 用作创建该Bean实例的元信息。

在用作对Bean的初次判断时,我们进行了第一次合并,放入缓存当中,并且之后的多次用作判断时它都是新鲜的。

我们在分析源码时,发现在getBean,也就是要创建该Bean实例时进行的一个判断,即不仅仅是类型检查,这时候会通过markBeanAsCreated来把该Bean的RootBeanDefinition改为不新鲜的(stale == true)。
AbstractBeanFactory#markBeanAsCreated
在这里插入图片描述

RootBeanDefinition在doGetBean中可能会再次进行修改

我们在上面已经知道,合并beanDefinition的执行一定是考虑到父BeanDefinition的影响,在第一次合并是这样,在第二次合并也不例外,这说明一点:

在doGetBean时,RootBeanDefinition一定不是最终形态,也就是说,在doGetBean后期阶段,会对RootBeanDefinition再次做出改变,因此执行父类bean(如我们示例中的RootBean)的实例创建时可能会修改RootBeanDefinition,既然父类BeanDefinition有了修改,子类BeanDefinition就不是新鲜的了,需要第二次合并,这也是就是在执行子类Bean的doGetBean时为什么要先设置为不新鲜的,因为考虑了这种可能。

doGetBean中哪个阶段可能会导致RootBeanDefinition做出改变?

问题:doGetBean中哪个阶段可能会导致RootBeanDefinition做出改变?

直接揭晓答案:在doGetBean之后执行createBean时的初期阶段可能会修改Bean,如果这时父BeanDefinition更新,那么毫无疑问,子BeanDefinition一定要合并更新信息。
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值