Spring三级缓存解决循环依赖

Spring

Spring解决循环依赖

描述:

A引用B, B引用A, 这样就构成了循环依赖

class A{
	B b;
}
class B{
	A a;
}

未使用Spring的情况下: 用构造方法的方式无法解决循环依赖, 但是使用set()可以

A a = new A(new B(new A(new B(new A(new B(...)))))) // 构造方法没有办法解决循环依赖
// 普通情况下使用set()可以解决循环依赖
A a = new A();
B b = new B();
a.setB(b);
b.setA(a);

使用set()后的打印结果:

我是A
我是B

Spring解决循环依赖: 三级缓存

/**
 *一级缓存:
 *单例对象的缓存: beanName - bean实例, 即所谓的单例池
 *表示已经经历了完整的生命周期的Bean对象
 **/
 private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
 /**
  *二级缓存:
  *时期的单例对象的缓存: beanName - bean实例
  *表示Bean的生命周期还没走完(Bean的属性还未填充)就把这个Bean存入二级缓存中
  *也就是二级缓存存的是实例化但未初始化的bean
 **/
 private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
 /**
  *三级缓存:
  *单例工厂的缓存: beanName - ObjectFactory
  *表示存放生成bean的工厂
  **/
 private final Map<String, ObjectFactory<?>> singletonFactoris = new HashMap<>(16);

在这里插入图片描述

过程:

  1. A创建过程中需要B, 于是A将自己放到三级缓存里面, 然后去实例化B
  2. B实例化的时候发现需要A, 于是B先查一级缓存, 没有, 再查二级缓存, 还是没有, 再三级缓存, 找到了A, 然后把三级缓存里面的这个放到二级缓存里面, 并删除三级缓存里面的A
  3. B顺利初始化完毕, 将自己放到一级缓存里面(此时B里面的A依然是创建状态), 然后回来接着创建A, 此时B已经创建结束, 直接从一级缓存里面拿到B, 然后完成创建, 并A自己放到一级缓存里面.

Spring为什么采用三级缓存的方式解决循环依赖?用二级缓存不可以吗?

原文链接:https://blog.csdn.net/qq_33468007/article/details/107814203

假如A和B都是被AOP增强的对象, 现在的A进行实例化, 并用A对B进行赋值, (这里的A的话是原生对象), 此时B开始创建并对A赋值, 此时, B注入的原生的A对象, B注入完成后被AOP增强, 所以B成为了代理对象, 然后A注入B的代理对象. 这里A注入完毕了, A通过AOP增强后也成为了代理对象. 这里就有很大的问题, 我们的A是代理对象, 而B注入的却是A的原生对象.

三级缓存的精妙

如果一个类是需要被增强的类,那么这个类会被提前增强,而且这里为什么会有AOP的缓存?道理也很简单,因此如果SpringAOP提前对user进行了增强,那么在依赖注入后的增强就会通过这个缓存判断是否已经被增强,这样就可以实现增强代码只实现一次,不重复增强user类,那么这就实现了注入的对象和原来的类是同一个。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值