SpringBoot框架03-Spring循环依赖

Spring 循环依赖

        

  1. 指两个或两个以上的Bean互相持有对方,最终形成闭环。Spring 的循环依赖的理论依据是基于Java的引用传递原理:当获得对象的引用时,对象的属性可延迟设置
  2. 两种循环依赖场景:
    1. 构造器的循环依赖,因为A中构造器注入了B,那么A在关键的方法addSingletonFactory()之前就去初始化了B,而B中构造器中又同时注入了A,导致三级缓存中根本没有A,所以会发生死循环,Spring发现后就抛出异常。
    2. 属性的循环依赖。Spring采用的是提前暴露对象的方法。只有单例对象才会有循环依赖。
  3. Spring 的单例对象初始化步骤:
    1. createBeanInstance:实例化,调用对象的构造方法实例化对象;
    2. populateBean:填充属性,依赖属性bean对象进行填充;
    3. initializaBean:Spring xml中的init 方法。
  4. Spring 解决循环依赖实现:
  • Spring 三级缓存
package org.springframework.beans.factory.support.AbstractBeanFactory

/** 一级缓存:存储已完成创建的Bean*/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** 三级缓存: 存储需要解决循环依赖而准备的实例对象*/
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

/** 二级缓存:存储正在创建状态的Bean,解决循环依赖而提早暴露出来的实例对象 */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

// 获取实例对象
@Nullable
protected Object getSingleton(String beanName, booleanallowEarlyReference) {
// 1.首先从一级缓存singletionObjects对象中获取
   Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//没有找到且处于正在创建状态
synchronized(this.singletonObjects) {
//2. 从二级缓存中获取
          singletonObject = this.earlySingletonObjects.get(beanName);
if(singletonObject == null && allowEarlyReference) {
//3.从三级缓存中获取
   ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if(singletonFactory != null) {
                   singletonObject= singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
                }
          }
      }
   }
return singletonObject;
}

// 将Bean添加到三级缓存singletonFactory中
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
      Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized(this.singletonObjects) {
if(!this.singletonObjects.containsKey(beanName)) {
//此时Bean已实例化,但属性值还未初始化,Spring认为是可以为复用状态了,所以将其放入singletonFactories三级缓存中
this.singletonFactories.put(beanName, singletonFactory);  
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);   //存储已注册的Bean
          }
      }
}

//将给定的单例对象添加到该工厂的单例缓存中。
protected void addSingleton(String beanName, Object singletonObject) {
synchronized(this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
    }
}

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值