循环依赖 三级缓存解决

循环依赖的产生
在这里插入图片描述
A对象里面依赖着B对象,B对象依赖着A对象
流程:
当A开始实例化A,然后初始化A,再初始化的A的时候,去实例化B,然后再初始化B,初始化B的时候在去实例化A,产生一个循环依赖。
spring设置三级缓存来解决这个问题
在这里插入图片描述
ObjectFactory是一个函数式接口,仅有一个方法,可以传入lambda表达式,可以是匿名内部类,通过调用getObject方法来执行具体的逻辑

1、一级缓存放成品对象
2、二级缓存放半成品对象
3、放lambda表达式,来完成代理对象的覆盖过程

三级缓存存的是lambda表达式 里面的一个getearlybean是解决三级缓存关键,底层是解决AOP动态代理,因为aop代理也要创建代理bean和普通bean,这时候和我们的spring中全局唯一bean产生了冲突,使用三级缓存解决。不知道是否需要使用aop代理,所以我们传入的是一个lambda表达式。什么时候调用,什么时候传进来,然后再进行判断,保证全局唯一

### Spring 框架中的三级缓存机制 Spring框架采用`singletonObjects`, `earlySingletonObjects`, 和 `singletonFactories`这三级缓存来处理循环依赖问题[^1]。 #### 单例模式下的Bean管理 当一个单例模式的Bean A正在创建过程中,另一个Bean B尝试注入它时,如果此时A还未完全初始化完成,则会触发循环依赖检测逻辑。为了应对这种情况,Spring设计了一套复杂的缓存策略: - **一级缓存 (`singletonObjects`)** 这是一个标准的缓存层,用来存储已经完全初始化完毕并可随时使用的单例Beans。一旦某个Bean完成了所有的初始化工作(包括属性设置、生命周期回调等),就会被放置到这里供其他组件使用[^4]。 - **二级缓存 (`earlySingletonObjects`)** 当前正在创建过程中的Bean,在其部分初始化状态下会被提前暴露给其他需要它的Beans。具体来说就是在这个阶段,即使Bean还没有完成全部配置项的赋值,也允许将其作为“早期版本”的形式提供出去。这种做法使得即便存在相互之间的引用关系,也能顺利完成各自的构建流程[^5]。 - **三级缓存 (`singletonFactories`)** 主要负责保存那些尚未准备好直接交付使用的Beans对应的工厂实例(`ObjectFactory`)。每当请求访问某特定名称下的Bean时,先检查是否有一级缓存命中;如果没有找到对应记录,则进一步查询是否有可用的对象工厂存在于此级别内。如果有匹配的结果,那么就通过调用该工厂的方法即时生产所需的对象,并立即将新产生的实体转移到更高级别的缓存中以便于后续重复利用[^3]。 #### 构造器引发的特殊情况 值得注意的是,对于由构造函数引起的循环依赖情况,上述方案并不适用。原因在于此类情形发生得非常早——甚至在任何类型的预设或代理之前就已经开始了。因此,在这个时候根本无法将任何一个不完整的对象加入到任一层次级别的缓存当中去[^2]。 ```java // 示例代码展示如何从三级缓存获取Bean public Object getBean(String beanName){ // 尝试从一级缓存获取 Object sharedInstance = singletonObjects.get(beanName); if (sharedInstance != null) { return getObjectForBeanInstance(sharedInstance, name); } // 如果不在一级缓存中,查看是否可以在二级缓存中找到 Object early SingletonObject = earlySingletonObjects.get(beanName); if (earlySingletonObject != null) { return earlySingletonObject; } // 否则考虑使用三级缓存里的factory生成目标bean ObjectFactory<?> objectFactory = singletonFactories.get(beanName); if(objectFactory!=null){ beforeSingletonCreation(beanName); try{ earlySingletonObjects.put(beanName,objectFactory.getObject()); singletonFactories.remove(beanName); afterSingletonCreation(beanName); return earlySingletonObjects.get(beanName); }catch(Throwable ex){ throw new BeansException("..."); } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值