Spring如何解决循环依赖

循环依赖:指多个bean之间相互依赖从而形成一个闭环。

即A依赖B,B依赖C,C依赖A这种。

 Spring中出现循环依赖的情况:

构造器注入:无法解决

多列setter注入:无法解决

单列setter注入:可通过三成缓存解决

Spring通过三层缓存解决依赖

三层缓存:

singletonObject:一级缓存,存放完成初始化的对象,可以直接使用
earlySingletonObject:二级缓存,存放早期对象的引用,尚未装配属性的对象
singletonFactories:三级缓存,存放完成实例化的对象工厂

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
	...
	// 从上至下 分表代表这“三级缓存”
    //一级缓存
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); 
    // 二级缓存
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); 
    // 三级缓存
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); 

初始化步骤:

  • createBeanInstance:实例化,即调用对象的构造方法实例化对象
  • populateBean:填充属性,主要对 bean 的依赖属性注入(@Autowired)
  • initializeBean:回到一些如initMethod,InitalizingBean等方法

过程简单介绍一下:

在有循环依赖的的时候,a对象初始化的流程中,将b对象也实例化和初始化了,在b的初始化过程中,将a从三级缓存移到了二级缓存中,当b初始化完成后继续向下执行,会执行到addSingleton()

protected void addSingleton(String beanName, Object singletonObject) {
        synchronized(this.singletonObjects) {
       // 将b加入到1级缓存
            this.singletonObjects.put(beanName, singletonObject);
            // 将b从三级缓存中删除
            this.singletonFactories.remove(beanName);
            // 将b从二级缓存中删除(b在二级缓存中没有,即空删除)
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }
    }

在b的所用工作做完之后,返回到a初始化属性b的代码,调用doCreateBean方法继续执行,最终也会到addSingleton()方法,将a也加入一级缓存,并且从二级缓存中删除a。这样a和b两个循环依赖的bean都被放入到一级缓存中。

系统启动获取配置文件后,程序是依次读取并加载的,所以当执行配置文件时,先获取a对象,如果获取不到则实例化a对象,然后初始化a对象即给a添加b属性,在添加b属性的时候先获取b,如果b存在则直接给a设置,不存在则实例化b,并且初始化b对象即给b添加对应的属性。

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
       // 先从一级缓存中获取a对象的实例
          Object singletonObject = this.singletonObjects.get(beanName);
           // 如果从一级缓存中获取不到a对象,那么检查该对象是否正在被创建,如果正在被创建,则进入if循环中
         if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
             synchronized(this.singletonObjects) {
            // 从二级缓存中获取该对象
                 singletonObject = this.earlySingletonObjects.get(beanName);
                   // 如果二级缓存中无法获取该对象,那么一定会进入如下if方法,因为allowEarlyReference传过来的时候就是true
                 if (singletonObject == null && allowEarlyReference) {
              // 从三级缓存中获取该对象
                     ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                     if (singletonFactory != null) {
                           // 如果获取到了该对象,就将三级缓存中的对象放到二级缓存中,并且将三级缓存中的对象删除
                         singletonObject = singletonFactory.getObject();
                         this.earlySingletonObjects.put(beanName, singletonObject);
                         this.singletonFactories.remove(beanName);
                     }
                 }
             }
         }
 
         return singletonObject;
     }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值