美文网首页
Bean的循环依赖

Bean的循环依赖

作者: Xr丶_c967 | 来源:发表于2020-03-14 19:45 被阅读0次

问题

public class A {
    private B b;
}

public class B {
    private A a;
}
/**********************/
<bean id="beanA" class="xyz.coolblog.BeanA">
    <property name="beanB" ref="beanB"/>
</bean>
<bean id="beanB" class="xyz.coolblog.BeanB">
    <property name="beanA" ref="beanA"/>
</bean>

Bean的实例化分三步

 createBeanInstance实例化 -> populateBean 填充属性 -> initializeBean初始化

如何解决

为了解决单例的循环依赖问题,使用了三级缓存,递归调用发现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
*/

比如:1) A创建过程中需要B,于是A先放入到三级缓存中,去实例化B
2) B实例化时需要A,于是B先查一级缓存,没有,在查二级缓存,还是没有,再查三级缓存,找到啦!
3)然后三级缓存里面这个A放到二级缓存中,并删除三级缓存里面的A
4) B初始化完毕,放入到一级缓存中(此时B中A还再创建中状态)
5)然后接着创建A,此时B已经创建结束,直接从一级缓存中拿到B,然后完成创建,并将自己放到一级缓
存里面

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    singletonObject = singletonFactory.getObject();
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

一句话:先让最底层对象完成初始化,通过三级缓存与二级缓存提前曝光创建中的 Bean,让其他 Bean 率先完成初始化。

相关文章

  • 循环依赖

    循环依赖 1、循环依赖的介绍 循环依赖,bean之间相互持有各自的引用,最终形成闭环。比如 bean的实例化有如下...

  • bean的循环依赖

    bean的循环依赖

  • spring中的循环依赖解决方案

    1. 什么是循环依赖? 一般场景是一个Bean A依赖Bean B,而Bean B也依赖Bean A.Bean A...

  • Spring 对于循环依赖的处理

    什么是循环依赖 循环依赖就是循环引用,就是两个或者多个bean相互之间的持有对方。 循环依赖的类型 构造器循环依赖...

  • Bean的循环依赖

    问题 Bean的实例化分三步 如何解决 为了解决单例的循环依赖问题,使用了三级缓存,递归调用发现Bean还在创建中...

  • spring-IOC 创建bean

    spring-IOC 创建bean 循环依赖 在创建bean的时候会存在依赖注入的情况,即A依赖B,B又依赖A。在...

  • Spring中的循环依赖

    1. 什么是循环依赖 当一个bean A依赖于另一个bean B,并且bean B也依赖于bean A时,就会发生...

  • spring常见面试题

    1. spring中bean的循环依赖?怎么解决? 循环依赖:在进行getBean时,A对象去依赖B对象,而B对象...

  • Spring的循环依赖问题

    什么是循环依赖 循环依赖也是循环引用,就是两个或多个Bean之间存在依赖关系,形成闭环 当Spring容器在创建A...

  • Spring是如何解决循环依赖的

    有两个bean,A依赖B,B依赖A,初始化时需要解决循环依赖。 (当然,如果bean是通过构造器注入的,则无法解决...

网友评论

      本文标题:Bean的循环依赖

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