spring中的循环依赖

spring中的循环依赖,第1张

spring中的循环依赖 spring中的循环依赖

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

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

private final Map singletonObjects = new ConcurrentHashMap<>(256);


private final Map earlySingletonObjects = new ConcurrentHashMap<>(16);


private final Map> 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 doGetBean(
      String name, @Nullable Class 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中解决循环依赖的方法

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5703753.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存