深夜头脑发热,悟道了Spring IOC的三级缓存

举个例子,A 对象内有 B 属性,创建 A 的时候通过名字 getBean 获取 A,getSingleton 发现缓存中没有 A 就去 createBean,实例化后会将工厂方法函数注册到第三级缓存 singletonFactories,然后在注入阶段 getBean 发现 getSingleton 缓存中找不到 B,就去 singletonFactory.getObject 回调调用 createBean 创建 B 对象,B 实例化后注册工厂函数到第三级缓存,然后注入 A 对象,而 getSingleton 这时候是可以在第三级缓存中找到 A 的工厂函数的,调用工厂的 getObject 方法,也就是调用工厂函数内的 getEarlyBeanReference 方法去获取早期 Bean 引用,内部的 A 被 AbstractAutoProxyCreator 后置处理器执行了一遍 AOP 代理,工厂调用得到的对象挪到第二级缓存 earlySingletonObjects,然后返回赋值给 B,这样 B 注入阶段结束,再初始化完成,也就是 createBean 完成,B 通过 addSingleton 挪到一级缓存。之前这个 B 的 getBean 逻辑是 A 调用的,A 完成了注入后,也可以最终完成初始化, createBean 完成,A 通过 addSingleton 挪到一级缓存。

Bean A 的创建流程Bean B 的创建流程一级缓存二级缓存三级缓存getBean("A") → 未找到createBean("A") → 实例化 A注册 A 的工厂到三级缓存开始属性注入(发现依赖 B)getBean("B")getBean("B") → 未找到createBean("B") → 实例化 B注册 B 的工厂到三级缓存开始属性注入(发现依赖 A)getBean("A") → 未找到getSingleton("A") → 未找到从三级缓存获取 A 的工厂调用 factory.getObject() → 触发 getEarlyBeanReference()生成 A 的代理对象(如有 AOP)将代理对象 A 存入二级缓存移除 A 的工厂将代理对象 A 注入到 B完成 B 的初始化将 B 存入一级缓存清理 B 的缓存(如有)获取到 B 的实例完成 A 的初始化将代理对象 A 存入一级缓存移除 A 的二级缓存Bean A 的创建流程Bean B 的创建流程一级缓存二级缓存三级缓存

以下是一些关键代码截图 ~~

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


实战中,构造器注入的循环依赖改为 @Autowired。用 prototype 注入失败时改代码。数据源注入失败时用 @Primary 来解决,或者指定 Bean 名称注入。异步的 @Async 如果有循环依赖就用@Lazy

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值