Spring循环依赖解决源码解析

本文深入探讨Spring框架如何通过三级缓存机制解决循环依赖问题,详细解释了构造方法注入及多例对象循环依赖为何无法解决,并阐述了单例对象在不同阶段的缓存策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

无法解决的循环依赖的方式

1) Spring无法解决构造方法注入引起的循环依赖问题
2) Spring无法解决多例对象的循环依赖问题,因为多例对象是不进行缓存的

循环依赖解决原理----三级缓存

//第一级缓存:缓存已经完成了实例化和属性设置的单例对象(单例对象缓存)
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);

解决步骤

doGetBean方法执行{
    //1.分别从三级缓存获取对象,第三级缓存命中会提升到缓存到二级
    Object sharedInstance = getSingleton(beanName); 
    //2.以下方法调用会先触发createBean方法创建Bean
    sharedInstance = getSingleton(beanName, () -> createBean(beanName, mbd, args)         	  	
    //3. createBean调用 doCreateBean
    //4.然后doCreateBean调用addSingletonFactory方法将创建的Bean封装在工厂引用中,放入三级缓存中
    //5.doCreateBean继续执行调用 populateBean方法设置属性,属性依赖Bean会触发继续调用doGetBean方法创建Bean,直到循环依赖的Bean被创建完,设置好依赖属性
    //6.结束doCreateBean后继续步骤2方法执行会调用addSingleton将Bean缓存到第一级缓存,清除二三级缓存
    doCreateBean调用addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
	 然后执行populateBean(beanName, mbd, instanceWrapper)设置属性,如果有依赖的Bean没有创建会触发doGetBean方法去创建依赖的Bean
}

相关方法

public Object getSingleton(String beanName) {
	return getSingleton(beanName, true);
}

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
	//从一级缓存中获取实例: 一级缓存用于缓存已经完成实例化的单例Bean
	Object singletonObject = this.singletonObjects.get(beanName);
	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
		synchronized (this.singletonObjects) {
            //从二级缓存中获取: 二级缓存用于缓存已经实例化的Bean,但是还没有设置依赖的类
			singletonObject = this.earlySingletonObjects.get(beanName);
			if (singletonObject == null && allowEarlyReference) {
                //从三级缓存获取:三级缓存用于缓存单例工厂,工厂封装了对应的创建Bean的方法
				ObjectFactory<?> singletonFactory = 
										this.singletonFactories.get(beanName);
				if (singletonFactory != null) {
                    //从工厂中获取单例
					singletonObject = singletonFactory.getObject();
                    //放入二级缓存中
					this.earlySingletonObjects.put(beanName, singletonObject);
                    //从三级缓存移除
					this.singletonFactories.remove(beanName);
				}
			}
		}
	}
	return singletonObject;
}

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封装到ObjectFactory中,保存到三级缓存
            this.singletonFactories.put(beanName, singletonFactory);
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }
    }
}

protected void addSingleton(String beanName, Object singletonObject) {
    synchronized (this.singletonObjects) {
        //Map缓存生成的单例名称与实例的映射
        this.singletonObjects.put(beanName, singletonObject);
        //移除缓存单例工厂,工厂是一个lamda表达式,可创建对应的实例对象
        this.singletonFactories.remove(beanName);
        //循环依赖时候暂时缓存未赋值完成的单例类,这里创建完成后移除缓存
        this.earlySingletonObjects.remove(beanName);
        //LinkedHashSet缓存已经注册了的单例Bean名称,用于检测重复注册的名字
        this.registeredSingletons.add(beanName);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值