几张图来好好理解Spring的循环依赖

Spring的循环依赖是什么?怎么解决

参考周瑜老师教学视频
类之间相互依赖本来是很正常的问题,但是在我们的Spring中就构成一个问题了

因为,在Spring中,一个对象并不是简单new出来了,而是会经过一系列的Bean的生 命周期,就是因为Bean的生命周期所以才会出现循环依赖问题。

当然,在Spring中, 出现循环依赖的场景很多,有的场景Spring自动帮我们解决了,而有的场景则需要程序员来解决,下文详细来说。

1.实例化Aservice

2.给其中的属性赋值,但是我们的Aservice中有一个属性值类型是Bservice(依赖Bservice)

那么首先Spring会先去单例池中去找我们的Bservice,如果找到了就返回,但是找不到就创建Bservice的Bean

​ 开始了Bservice的生命周期

2.1 实例化Bsevice对象

2.2为其中的属性赋值(有Aservice属性),同理单例池中找Aservice的Bean,但是这个时候是找不到的因为 Aservice还没有初始化完的。。。。难道我们的Spring还会继续去新建Aservice么?

一级缓存就是单例池:singletonObjects,是一个map对象
在这里插入图片描述
怎么解决?
在这里插入图片描述
怎么知道我们要提前AOP呢?

当出现循环依赖的时候,我们就提前进行AOP,那又怎么样判断是否出现循环依赖呢?

实例化对象之前,将我们要实例化的对象放入一个Set中,只要在这个Set中,就说明我们的对象还在实例化,然后继续进行,然后发现Bservice要实例化,也加入到Set中,然后属性填充的时候发现又需要aservice对象,单例池没有,而且我们的Set中有Aservice对象正在创建,就表明是发生了循环依赖,就会进行我们的提前AOP

新的问题,再来个Cservice,也用到了aservice,Aservice中也有Cservice的属性,那我要生成两个Aservice的代理对象么?
不用,这就是我们的二级缓存的工作,earlySingletonObjects,也是一个map,他会判断如果这个map中已经存在了一个Aservice的代理对象,就不会在就AOP了,直接拿过来用,简单来说就是来保证我们的单例特点的(不完整的对象)

然后我们是从我们的二级缓存中拿到我们的对象,放进单例池

那三级缓存是啥呢?
上面还有一个问题,既然我们想要提前AOP,我们就得拿到我们的原始对象(target),怎么拿到这个原始对象呢?

这就需要我们的三级缓存,map对象存储的是<beanName,Aservice原始对象,bean的定义>,这就是我们的三级缓存spring源码 存的是一个lamdba表达式

map.put(beanName,lambda(beanName,BeanDefinition,Aservice原始对象));//拿到Bean的定义,就会知道我们要不要进行AOP

真正的名字是叫做singletonFactorys
在这里插入图片描述
为什么一级缓存用的ConcurrentHashMap,而我们的二级三级缓存用的是HashMap呢?

因为二级三级缓存是同时操作的,源码中也体现出来了,我们向二级缓存加beanName就会把三级缓存这个beanName删除掉,在我们用三级缓存加beanName的时候,不管二级缓存有没有也会删除掉二级缓存同一个名字的beanName,就像是一个原子的操作,就算你来用CHashMap也无法保证,所以是在外面的方法加锁了,就没必要用CuHashMap了。

既然我提前AOP了,那后面我就不用AOP了,后面怎么判断我要不要在AOP呢?

有两个方法

getEarlyBeanReference,这个是我们提前AOP走的方法

而且我们发现,这个方法其实就是我们的那个三级缓存中的那个lambda表达式

在这里插入图片描述
一个是

postProcessAfterInitialization方法,这个是正常初始化走的AOP方法,这个方法中会去判断:从这个map移除出来一个bean看看是不是原始bean是的话,就说明我们已经提前进行了AOP
这个也是一个map,Cmap用来判断某个类有没有提前进行AOP

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

会写代码的花城

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值