Spring的循环依赖还不会?

Spring的循环依赖还不会?

一、什么是循环依赖?

循环依赖就是循环引用,就是两个或多个bean相互之间的持有对方,比如CircleA引用CircleB,CircleB引用CircleA,则它们最终反映为一个环。例如:

public class A{
    private B b; 
}

public class B{
    private A a;
}

//A和B两个对象,A对象中引用B,B对象中引用A,这样就形成了循环依赖

二、如何解决循环依赖问题?

注入方式是setter且singleton, 就不会有循环依赖问题,解决循环依赖主要使用了三级缓存的概念,下面将详细介绍三级缓存以及三级缓存是如何解决循环依赖问题的。

构造器注入没有办法解决循环依赖, 想让构造器注入支持循环依赖,是不存在的

三、什么是三级缓存

所谓的三级缓存其实就是spring容器内部用来解决循环依赖问题的三个Map。

	/** Cache of singleton objects: bean name to bean instance. */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** Cache of singleton factories: bean name to ObjectFactory. */
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

	/** Cache of early singleton objects: bean name to bean instance. */
	private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
  • 第一级缓存(也叫单例池)singletonObjects:存放已经经历了完整生命周期的Bean对象

  • 第二级缓存: earlySingletonObjects,存放早期暴露出来的Bean对象,Bean的生命周期未结束(属性还未填充完整)

  • 第三级缓存: Map<String, ObiectFactory<?>> singletonFactories,存放可以生成Bean的工厂

四、三级缓存是如何解决循环依赖问题的?

1.对象产生的过程

创建对象的时候,主要会经历四个方法,分别是:getSingleton,doCreateBean,populateBean,addSingleton

  • getSingleton:希望从容器里面获得单例的bean,没有的话执行方法2
  • doCreateBean: 没有就创建bean
  • populateBean: 创建完了以后,要填充属性
  • addSingleton: 填充完了以后,再添加到容器进行使用

2.循环依赖产生的示意图

在这里插入图片描述

如上图所示,当新创建A和B两个对象的时候,就会形成闭环,造成循环依赖的现象,三级缓存就是用来打破闭环,解决循环依赖。

引入三级缓存之后,效果如下:有专门存放半成品的缓存,就不会陷入闭环的尴尬。

在这里插入图片描述

3.对象的迁移过程

  • 示意图

在这里插入图片描述

  • 文字描述

    1. getBean在容器(包括一二三级缓存)中获得A对象,没有则创建A对象;
    2. 初始化A对象,将A对象的ObjectFactory的lamda放入三级缓存;
    3. populateBean,填充属性B对象;
    4. getBean在容器(包括一二三级缓存)中获得B对象,没有则创建B对象;
    5. 初始化B对象,将B对象的ObjectFactory的lambda放入三级缓存;
    6. populateBean,填充属性A对象,在三级缓存中找到A对象(正在创建中的A对象);
    7. 调用A的ObjectFactory,创建半成品,将创建好的半成品放到二级缓存,并将三级缓存中的A移除;
    8. 取到A对象之后,给B对象中的A属性赋值,那么此时B对象则创建完成,放到一级缓存,三级缓存删除B;
    9. 此时再给A对象中的B对象赋值,将成品A放到一级缓存,将二级缓存中的A删除;
    10. 此时A对象创建完成,再创建B对象,但是在容器中直接拿到了B对象,则无需再次创建,完工。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值