本仓库以 Spring
源码学习为目的,通过手写简化版 Spring
框架,了解 Spring
核心原理。关于过程中的笔记我放在了博客中
在手写的过程中会简化 Spring
源码,摘取整体框架中的核心逻辑,简化代码实现过程,保留核心功能,例如:IOC
、AOP
、Bean
生命周期、上下文、作用域、资源处理等内容实现。整个项目涉及到的Bean
生命周期如下图所示:
下面提供一个仓库目录,针对每一章都有一个博客来详细介绍项目中新增的内容
- 第一章:实现一个简单的
Bean
容器 - 第二章:将
Bean
的创建交给IOC
容器 - 第三章:实现带参的
Bean
创建 - 第四章:将
Bean
的创建和属性填充分开 - 第五章:实现从配置文件中加载
Bean
的注册信息 - 第六章:实现应用上下文,后置处理器
- 第七章:添加初始化和销毁模块
- 第八章:
Aware
回调注入容器资源 - 第九章:多种模式以及多种方式创建
Bean
对象 - 第十章:事件机制的实现
- 第十一章:引入
AOP
机制 - 第十二章:自动扫描
Bean
对象以及属性占位符的使用 - 第十三章:通过注解给
Bean
注入依赖的属性 - 第十四章:通过延缓代理对象的创建时机从而给代理对象进行属性填充
- 第十五章:利用三级缓存解决循环依赖
经过上面的填充,简化版 Spring
框架已经有了一定的规模,下面介绍在Bean
的生命周期中都加入了哪些模块:
-
首先
spring
框架需要读取xml
配置文件,然后将配置的所有Bean
的注册信息保存到BeanDefinition
中 -
之后就是触发实例化前的修改逻辑,内部可以将
Bean
中使用占位符形式填充的属性换成真正的属性值。 -
下一步将实例化后的处理逻辑先保存到容器中,在实例化之后直接触发即可。
-
然后需要初始化一个事件广播器并将其保存到
IOC
容器中,当事件发生时由事件广播器通知事件监听器从而执行对应的操作。 -
之后就是事件监听器的实例化,将其保存到上一步中的事件广播器中,事件经过事件广播器的发布之后,对应的事件监听器就会得到通知
-
然后进行所有
Bean
的第一次实例化,在这一步加入了类型转换的服务,内部保存了很多的类型转换器,之后就是实例化所有的Bean
-
第一次实例化所有的
Bean
时,单例池中并没有需要的Bean
,所以需要从头创建,首先创建一个空Bean
,创建完成之后判断是不是FactoryBean
类型的Bean
,如果是的话需要从其中取出真正的Bean
返回 -
将创建的空
Bean
的信息保存到三级缓存中,便于后期出现循环依赖时使用,而循环依赖中会提前尝试AOP
,从而得到Bean
的原始对象或者代理对象。这也导致后面正常的AOP
过程不一定会触发 -
三级缓存中,每一级缓存的作用都不相同,大致区别如下:
- 三级缓存:保存一个
lambda
表达式,调用其中的getObject
方法就能获得一个尝试代理之前的对象,用来打破循环依赖 - 二级缓存:用来保存尝试过代理后的
Bean
,保持Bean
的单例性 - 一级缓存:保存实例化完成之后的
Bean
,便于复用,这里的Bean
已经是完成态
- 三级缓存:保存一个
-
然后就是属性填充,有两种属性填充的方式,首先进行注解属性填充
-
然后进行普通的
xml
文件配置的属性填充 -
之后使用
Aware
回调机制实现容器资源的注入 -
之后执行初始化前的逻辑,主要是执行应用上下文的容器资源注入
-
初始化执行逻辑中主要是执行初始化方法,初始化方法有两种方式,一种实现对应的接口,一种是在
xml
文件中配置指定初始化方法的名称 -
初始化后的逻辑中进行正常
AOP
的操作,由于前面可能对Bean
进行提前AOP
,这里不一定触发 -
之后就是将销毁方法注册到钩子函数中,在容器销毁之前进行调用
-
经历上面的步骤之后,
Bean
创建完成,之后将单例Bean
保存到单例池中 -
后期再使用时走到第7步时就先尝试从单例池中拿,拿不到才会重新创建
以上的步骤只是精简过后描述的Bean
的生命周期,细节需要查看提供的代码,代码在开发过程中参考了小傅哥的文章,从文章中受益匪浅。