美文网首页
循环依赖问题

循环依赖问题

作者: 晨曦_lcq | 来源:发表于2020-07-26 20:44 被阅读0次

    问题描述

    有多个对象,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。

    相关文章

      网友评论

          本文标题:循环依赖问题

          本文链接:https://www.haomeiwen.com/subject/wleglktx.html