Spring 源码学习 04:初始化容器与 DefaultListableBeanFactory
前言

在前一篇文章:创建 IoC 容器的几种方式中,介绍了四种方式,这里以 AnnotationConfigApplicationContext 为例,跟进代码,看看 IoC 的启动流程。
入口
从 JavaConfig 中加载配置的 AnnotationConfigApplicationContext 启动方式如下:

进去之后发现构造其实是调用的当前无参构造。

所以在启动时也可以直接声明无参构造,改写为下面这种:
public class AnnotationConfigApplicationTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(JavaConfig.class);
context.refresh();
System.out.println(context.getBean(UserComponent.class));
}
}
今天就研究研究无参构造这一部分究竟做了什么逻辑!
无参构造

其中的 StartupStep 是 5.3 新增的类,看代码注释的意思是:表示用来记录启动过程中的一些指标信息等。暂时不做研究。
主要研究红框部分!注意,这一块并不代表只有红框部分!

因为 AnnotationConfigApplicationContext 继承了 GenericApplicationContext,所以会先执行父类的构造方法。

所以这里会创建一个 DefaultListableBeanFactory 的容器。
DefaultListableBeanFactory

虽然说 Spring 的 BeanFactory 定义了容器的基础概念、接口方法等,但是 DefaultListableBeanFactory 才是一个真正可以 new 出来的具体的容器,当然也可以暂且称之为 bean 工厂。
下面来看一下 DefaultListableBeanFactory 里面都有什么?

在 DefaultListableBeanFactory 里面会初始化很多参数,其中重点关注的是下面两个参数:
/** Map of bean definition objects, keyed by bean name. */
// BeanDefinition 的存储 Map 其中 key 为 beanName
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
/** List of bean definition names, in registration order. */
// BeanName 的集合
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
其中 BeanDefinition 描述了一个 bean 实例,该实例具有属性值,构造函数参数值以及具体实现所提供的更多信息。
对应的 beanDefinitionMap 就是存储的初始化的 beanName 和 BeanDefinition。
至于 BeanDefinition 具体内容,下一节再做介绍。
总结
通过上面的阅读,可以在初始化流程中增加一部分模块,即实例化 DefaultListableBeanFactory

再回顾一下 DefaultListableBeanFactory 的概念。
DefaultListableBeanFactory:
Spring 的 ConfigurableListableBeanFactory 和 BeanDefinitionRegistry 接口的默认实现:基于bean定义元数据的成熟bean工厂,可通过后处理器进行扩展。
重点需要把握的是 DefaultListableBeanFactory 内部定义了 BeanDefinition 的 Map。
结束语
本文从入口开始,进入到构造,主要介绍了 DefaultListableBeanFactory 的创建,及创建时初始化了一堆参数。
考虑到文章篇幅问题,尽量避免大段大段的贴代码以及注释,有兴趣的小伙伴可以试着自己搭建源码构建环境,然后 Debug 走一走,这样也可以互相探讨,共同学习。
笔者也是刚开始阅读学习源码,不足之处,希望多多指正。
相关推荐
Spring 源码学习 04:初始化容器与 DefaultListableBeanFactory的更多相关文章
- spring源码学习笔记之容器的基本实现(一)
前言 最近学习了<<Spring源码深度解析>>受益匪浅,本博客是对学习内容的一个总结.分享,方便日后自己复习或与一同学习的小伙伴一起探讨之用. 建议与源码配合使用,效果更嘉, ...
- Spring源码学习之IOC容器实现原理(一)-DefaultListableBeanFactory
从这个继承体系结构图来看,我们可以发现DefaultListableBeanFactory是第一个非抽象类,非接口类.实际IOC容器.所以这篇博客以DefaultListableBeanFactory ...
- 【spring源码分析】IOC容器初始化(总结)
前言:在经过前面十二篇文章的分析,对bean的加载流程大致梳理清楚了.因为内容过多,因此需要进行一个小总结. 经过前面十二篇文章的漫长分析,终于将xml配置文件中的bean,转换成我们实际所需要的真正 ...
- 【spring源码分析】IOC容器初始化(七)
前言:在[spring源码分析]IOC容器初始化(六)中分析了从单例缓存中加载bean对象,由于篇幅原因其核心函数 FactoryBeanRegistrySupport#getObjectFromFa ...
- 【spring源码分析】IOC容器初始化(十)
前言:前文[spring源码分析]IOC容器初始化(九)中分析了AbstractAutowireCapableBeanFactory#createBeanInstance方法中通过工厂方法创建bean ...
- Spring源码学习-容器BeanFactory(四) BeanDefinition的创建-自定义标签的解析.md
写在前面 上文Spring源码学习-容器BeanFactory(三) BeanDefinition的创建-解析Spring的默认标签对Spring默认标签的解析做了详解,在xml元素的解析中,Spri ...
- Spring源码学习-容器BeanFactory(三) BeanDefinition的创建-解析Spring的默认标签
写在前面 上文Spring源码学习-容器BeanFactory(二) BeanDefinition的创建-解析前BeanDefinition的前置操作中Spring对XML解析后创建了对应的Docum ...
- 【spring源码分析】IOC容器初始化——查漏补缺(一)
前言:在[spring源码分析]IOC容器初始化(十一)中提到了初始化bean的三个步骤: 激活Aware方法. 后置处理器应用(before/after). 激活自定义的init方法. 这里我们就来 ...
- 【spring源码分析】IOC容器初始化(二)
前言:在[spring源码分析]IOC容器初始化(一)文末中已经提出loadBeanDefinitions(DefaultListableBeanFactory)的重要性,本文将以此为切入点继续分析. ...
随机推荐
- python中的evalexec 将字符串当做代码执行
eval/exec 将字符串当做代码执行 eval/exec 这两个函数可以将字符串解析为代码并执行. 区别 1.eval 解析变量和表达式, 而 exec 解析语句 a = '1' print(ev ...
- django JsonResponse返回中文时显示unicode编码(\u67e5\u8be2)
django JsonResponse返回中文时显示unicode编码(\u67e5\u8be2) 关注公众号"轻松学编程"了解更多. 原因 这个unicode编码,是python ...
- 快速傅里叶变换学习笔记(FFT)
什么是FFT FFT是用来快速计算两个多项式相乘的一种算法. 如果我们暴力计算两个多项式相乘,复杂度必然是\(O(n^2)\)的,而FFT可以将复杂度降至\(O(nlogn)\) 如何FFT 要学习F ...
- 【Java】阿里巴巴开发规范手册
Java 开发手册 一. 编程规约 (一) 命名风格 [强制]代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束. 反例: _name, $name, __name [强制]代码中 ...
- dhcp、tftp、httpd、pxe安装CentOS6.9
虚拟机网络设置 要xshell连接虚拟机注意设置VMware Network Adapter VMnet2在同一网段 1.利用光盘配置本地yum源 [root@ZYB ~]# mount -r /de ...
- kubernetes-1.18.2集群安装-02
一.基础配置 修改主机名 # 在 172.17.32.23 上:hostnamectl set-hostname k8s-master01bash# 在 172.17.32.38 上:hostnam ...
- 08flask中get和post请求。
1,get请求. 使用场景:获取信息并没有对服务器的数据或者资源进行修改,则用get. 传参:get请求传参是放在URL中,通过"?"的形式指定键值对. 2,post请求. 使用场 ...
- Effective Modern C++ ——条款5 优先选择auto,而非显式型别声明
条款5 对于auto ,他的好处不仅仅是少打一些字这么简单. 首先在声明的时候, 使用auto会让我们养成初始化的习惯: auto x;//编译不通过必须初始化. 再次对于auto而言,它可以让我们定 ...
- 在Linux深度系统deepin下安装docker
wget -qO- https://get.docker.com/ | sh wget -qO- https://get.docker.com/ | sh
- JAVA基础之接口与内部类
接口与内部类 目录 接口与内部类 1. Lambda表达式 1. 关于懒计算 2. Predicate接口 3. 关于方法引用 4. 关于构造器引用 5. 关于变量的作用域 2. 内部类 1. 局部内 ...