#yyds干货盘点# Spring源码三千问BeanDefinition详解——什么是 RootBeanDefinition(merged bean definition 又是什么鬼?)
盛年不重来,一日难再晨,及时当勉励,岁月不待人。这篇文章主要讲述#yyds干货盘点# Spring源码三千问BeanDefinition详解——什么是 RootBeanDefinition?merged bean definition 又是什么鬼?相关的知识,希望能为你提供帮助。
@TOC
前言从接触 Spring 源码之后,我就对 BeanDefinition 早已耳熟能详,但一直没有深入研究过它的作用,以至于每次在读源码过程中碰到 BeanDefinition 时有种熟悉又陌生的感觉。
BeanDefinition 是 Spring IoC 体系中的一个重要概念,如果不能深入理解它,那么必定不能很好的理解 Spring IoC 的底层原理。
所以,就让我们一起来消灭掉这个熟悉又陌生的"
敌人"
吧!
版本约定【#yyds干货盘点# Spring源码三千问BeanDefinition详解——什么是 RootBeanDefinition(merged bean definition 又是什么鬼?)】Spring 5.3.9 (通过 SpringBoot 2.5.3 间接引入的依赖)
正文先从类的继承关系图这个顶层视角来了解一下 BeanDefinition 吧!
文章图片
RootBeanDefinitionRootBeanDefinition 本质上是 Spring BeanFactory 运行时统一的 BeanDefinition 视图。
它代表了一个 merged bean definition,是 Spring BeanFactory 在运行时支持的一个特殊的 bean。
自 Spring 2.5 以来,以编程方式注册 bean 定义的首选方法是 GenericBeanDefinition 类。GenericBeanDefinition 的优点是它允许动态定义父依赖项,而不是将角色“硬编码”为 RootBeanDefinition。
通过上面的解释,可以看出 RootBeanDefinition 的江湖地位可不小!它是 Spring BeanFactory 运行时统一的 BeanDefinition 视图。
在 Spring 源码中,我们也可以看到,Spring 在通过 BeanDefinition 创建 bean 的实例时,通常都会将 BeanDefinition 转化为 RootBeanDefinition 后,再进行 bean 实例的创建。
GenericBeanDefinitionGenericBeanDefinition 是以编程方式注册 BeanDefinition 的首选类。
它除了可以指定一些基本的 BeanDefinition 属性外,还可以通过“setParentName()”来灵活地配置 parent bean definition。
所以,GenericBeanDefinition 基本上可以完全替代掉 ChildBeanDefinition。
ChildBeanDefinition它是一种可以继承 parent 配置的 BeanDefinition。
在创建 bean 时,会通过 AbstractBeanFactory#getMergedLocalBeanDefinition() 来将 child 和 parent bean definition 进行合并。
看一个例子:
StaticApplicationContext parent = new StaticApplicationContext();
StaticApplicationContext child = new StaticApplicationContext(parent);
RootBeanDefinition pbd = new RootBeanDefinition();
pbd.setBeanClass(FooService.class);
pbd.setScope(BeanDefinition.SCOPE_SINGLETON);
pbd.getPropertyValues().add("id", "123");
pbd.getPropertyValues().add("name", "zhangsan");
parent.registerBeanDefinition("fooService", pbd);
ChildBeanDefinition cbd = new ChildBeanDefinition("fooService");
cbd.setBeanClass(FooService.class);
cbd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
cbd.getPropertyValues().add("id", "456");
child.registerBeanDefinition("fooService", cbd);
// 通过子容器来获取 bean
FooService bean1 = child.getBean(FooService.class);
FooService bean2 = child.getBean(FooService.class);
System.out.println(bean1 + ",id=" + bean1.getId() + ",name=" + bean1.getName());
System.out.println(bean2 + ",id=" + bean2.getId() + ",name=" + bean2.getName());
输出结果:
com.kvn.beans.child.FooService@146ba0ac,id=456,name=zhangsan
com.kvn.beans.child.FooService@4dfa3a9d,id=456,name=zhangsan
可以看出 getMergedLocalBeanDefinition() 时,会以 ChildBeanDefinition 的属性为准,同时,将 parent BeanDefinition 的属性合并进来。
merged bean definition它不是一个具体的类,而是 Spring 对 BeanDefinition 进行的一种合并操作。
Spring 什么时候会对 BeanDefinition 进行 merge 操作呢?
答:在根据 BeanDefinition 创建 bean 的实例之前,会通过
AbstractBeanFactory#getMergedLocalBeanDefinition()
来进行 merge 操作。文章图片
BeanDefinition 的 merge 操作的作用是什么?
答:对 BeanDefinition 进行 merge 操作时,会将 child 的属性与 parent 的属性进行合并,当有相同属性时,以 child 的为准。
而类似 propertyValues、constructor args 这种集合类的参数属性的话,就会取并集。
所以,上面 ChildBeanDefinition 例举的例子中,ChildBeanDefinition 中并没有 name 这个属性,而通过子容器获取到的 FooService bean 中的 name 却有了值,并且值是 parent BeanDefinition 中的属性值。
这也证明了 child 与 parent 的 BeanDefinition 属性会进行合并。
小结本文重点讲解了 RootBeanDefinition、ChildBeanDefinition、GenericBeanDefinition、merged bean definition
其中重点需要掌握的有:
- RootBeanDefinition
它是 Spring BeanFactory 运行时统一的 BeanDefinition 视图
- GenericBeanDefinition
它是以编程方式注册 BeanDefinition 的首选类
- merged bean definition
它不是一个具体的类,而是 Spring 对 BeanDefinition 进行的一种合并操作。
merge 操作会将 child 的属性与 parent 的属性进行合并,当有相同属性时,以 child 的为准。
有关 Spring 源码方面的问题欢迎一起交流,备注:51cto (vx: Kevin-Wang001)
博主好课推荐:
课程 | 地址 |
---|---|
Dubbo源码解读——通向高手之路 | https://edu.51cto.com/course/23382.html |
正则表达式基础与提升 | https://edu.51cto.com/course/16391.html |
推荐阅读
- #yyds干货盘点#dart系列之:如丝滑般柔顺,操作文件和目录
- #yyds干货盘点#--三分钟搭建一套内网的yum本地源
- #私藏项目实操分享#Java多线程下载器项目实例之线程池
- C# 扫描识别图片中的文字(.NET Framework)
- 从一次 SQL 查询的全过程看 DolphinDB 的线程模型
- #星光计划2.0# linux内核增加HDF驱动子系统
- 学习Java必备的基础知识打卡12.16,要想学好必须扎实基本功(?建议收藏)#yyds干货盘点#
- Python | Python常用函数方法示例总结(API)#yyds干货盘点#
- 声临其境,轻松几步教你把音频变成3D环绕音