spring中的循环依赖

spring中的循环依赖

循坏依赖指的是,A对象中持有B对象的引用,而B对象中持有A对象的引用,他们之间形成了循环依赖。或者是多个对象之间A依赖于B,B依赖于C,C又依赖A,形成循环依赖。又或者是对象自己依赖于自己。

image-20220111004002196

在spring中实际上是使用三级缓存来解决循环依赖的,spring中的三级缓存分别是

/** 一级缓存,这里存放的对象是属性已经赋值完成的对象 */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** 二级缓存,用于存放实例化完成但是还未对属性赋值的对象 */
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);

/** 三级缓存,存放生成单例bean的工厂 */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

创建两个循环依赖的对象

@Component
public class A {

    @Autowired
    private B b;

}
@Component
public class B {

    @Autowired
    private A a;
    
}

spring中遇到循环依赖对象的创建步骤

1.在创建A对象时会先创建一个ObjectFactory工厂类

2.调用populateBean向A对象中注入属性

具体代码如下(AbstractAutowireCapableBeanFactory抽象类中的方法)

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {
    ......
   boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
         isSingletonCurrentlyInCreation(beanName));
   if (earlySingletonExposure) {
      if (logger.isTraceEnabled()) {
         logger.trace("Eagerly caching bean '" + beanName +
               "' to allow for resolving potential circular references");
      }
       //向第三级缓存中添加一个,ObjectFactory工厂类
      addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
   }
    Object exposedObject = bean;
    try {
        //向对象中注入属性
        populateBean(beanName, mbd, instanceWrapper);
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
    catch (Throwable ex) {
        if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
            throw (BeanCreationException) ex;
        }
        else {
            throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
        }
    }
	......
}

3.在注入属性时会在容器中寻找B对象但是没有找到B对象,则开始B对象的创建流程

4.在B对象的创建过程中同样会调用上面代码中的populateBean方法向B对象中A对象

5.这时候会调用getBean方法获取A对象

@Override
public Object getBean(String name) throws BeansException {
   return doGetBean(name, null, null, false);
}

6.在获取A对象的时候会从缓存中尝试获取,这时候从三级缓存中可以获取到A对象的工厂

protected <T> T doGetBean(
      String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
      throws BeansException {
	
   String beanName = transformedBeanName(name);
   Object beanInstance;

   // 这个方法里面就会创建A对象并且放入第二级缓存中
   Object sharedInstance = getSingleton(beanName);
   if (sharedInstance != null && args == null) {
      if (logger.isTraceEnabled()) {
         if (isSingletonCurrentlyInCreation(beanName)) {
            logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                  "' that is not fully initialized yet - a consequence of a circular reference");
         }
         else {
            logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
         }
      }
      beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
   }
	......
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        singletonObject = this.earlySingletonObjects.get(beanName);
        if (singletonObject == null && allowEarlyReference) {
            synchronized (this.singletonObjects) {
                singletonObject = this.singletonObjects.get(beanName);
                if (singletonObject == null) {
                    singletonObject = this.earlySingletonObjects.get(beanName);
                    if (singletonObject == null) {
                        //获取到前面第一步中放入的ObjectFactory
                        ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                        if (singletonFactory != null) {
                            //创建A对象
                            singletonObject = singletonFactory.getObject();
                            //将A对象放入第二级缓存中
                            this.earlySingletonObjects.put(beanName, singletonObject);
                            //将第三级缓存中的A对象的ObjectFactory移除
                            this.singletonFactories.remove(beanName);
                        }
                    }
                }
            }
        }
    }
    return singletonObject;
}

以上就是spring中解决循环依赖的方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值