循环依赖问题

问题描述

有多个对象,A依赖B,B依赖A。导致实例化的时候会进入死循环导致内存溢出。

三种循环依赖

1.构造器的循环依赖(spring解决不了)

构造器中包含其他bean,spring容器会将每个正在创建的bean放在三级缓存中,并且创建过程中一直放在这个三级缓存中,如果在创建bean的过程中,发现自己已经在三级缓存中就抛出BeanCurrentlyInCreatingException。

2.setter方式,单例模式(spring能解决)

@Service
public class A {
    @Autowire
    private B b;
}
@Service
public class B {
    @Autowire
    private A a;
}

解决方案

使用了三级缓存。创建Bean分为3个阶段,实例->赋值属性->初始化,递归调用时发现Bean还在创建中即为循环依赖。

/** 一级缓存:用于存放完全初始化好的 bean **/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);

/** 二级缓存:存放原始的 bean 对象(尚未填充属性),用于解决循环依赖 */
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);

/** 三级级缓存:存放 bean 工厂对象,用于解决循环依赖 */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
/**
bean 的获取过程:先从一级获取,失败再从二级、三级里面获取
创建中状态:是指对象已经 new 出来了但是所有的属性均为 null 等待被 init
*/

检测循环依赖的过程

  • A创建过程中需要B,先将自己放到3级缓存中,去实例化B
  • B实例化的时候需要A,会去一级缓存中查看是否有A,如果没有就去二级缓存,发现还是没有就去三级缓存,找到了
    • 把3级缓存里的A放到二级缓存,并删除3级缓存里的A
    • B初始化完毕,将自己放到一级缓存里
  • 然后回来接着创建A,此时B已经创建结束,直接从一级缓存中找到B,然后完成创建,并将自己A放到一级缓存中
  • 顺利创建完A

3.setter方式,原型模式

spring解决不了,prototype作用域的bean,spring容器不进行缓存,无法暴露正在创建的bean。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。