Spring容器 之 循环依赖终极讲解

一、问题重现

情况一

SelfDependencyBean 中含有 SelfDependencyBean 属性并且需要依赖注入。

情况二

OrderServiceImpl 中含有 UserServiceImpl 属性并且需要依赖注入;
UserServiceImpl 中含有 OrderServiceImpl 属性并且需要依赖注入。

反正嘛,就是形成了循环的依赖关系就是这个意思。

如果单例的情况,Spring会自动帮你解决;而多例的情况,从逻辑上是会造成无限递归导致内存溢出,所以spring并不会帮你擦屁股哦。

二、知识预热

1. Spring容器中使用到的集合

  • Set< String> singletonsCurrentlyInCreation:准备初始化的对象
  • Map<String, Object> singletonObjects:已实例化+赋值完成对象
  • Map<String, Object> earlySingletonObjects:早期对象(仅完成了实例化的对象)
  • Map<String, ObjectFactory<?>> singletonFactories:bean实例化的工厂类

2. 核心代码解析(节选+伪代码)

备注

  1. >>> 是调用的意思
  2. -> 是lambda表达式

DefaultListableBeanFactory

	// 对象注册bean入口
	getBean(beanName) >>> doGetBean(name, null, null, false) {
		getSingleton(beanName)
		getSingleton(beanName, () -> createBean(beanName, mbd, args))
	}

AbstractBeanFactory

	// 从缓存、早期对象、objectFactory集合中获取Bean对象
	getSingleton(beanName, true)
	
	// 标记当前bean对象的状态存入到集合中,并完成创建赋值
	getSingleton(beanName, () -> createBean(beanName, mbd, args)) {
		// 标记当前bean为初始化状态
		beforeSingletonCreation(beanName)
		// 创建对象,并且完成属性赋值
		singletonObject = singletonFactory.getObject() -> createBean(beanName, mbd, args)
		// 移除当前bean的初始化状态
		afterSingletonCreation(beanName)
		// 加入缓存
		addSingleton(beanName, singletonObject)
	}

AbstractAutowireCapableBeanFactory

	// 创建对象,并且完成属性赋值
	createBean(beanName, mbd, args) >>> doCreateBean(beanName, mbdToUse, args) {
		// 使用反射技术,实例化对象
		instanceWrapper = createBeanInstance(beanName, mbd, args);
		// 当前类是单例 && 允许循环依赖 && 当前bean为初始化状态
		if (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)){
			// 当前bean的工厂类加到准备实例化的objectFactory集合中
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean))
		}
		// 属性赋值
		populateBean(beanName, mbd, instanceWrapper);
		// 执行bean的各种init方法+执行前后置处理器
		exposedObject = initializeBean(beanName, exposedObject, mbd);
		return instanceWrapper;
	}

	// 当前bean的工厂类加到准备实例化的objectFactory集合中
	addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean))

	// 属性赋值
	populateBean(beanName, mbd, instanceWrapper) {
		...
		getBean(beanName)
		...
	}

简单粗暴集成Spring递归调用getBean方法—— 执行过程

getBean(OrderServiceImpl) >>> doGetBean(OrderServiceImpl, null, null, false) {
	getSingleton(OrderServiceImpl) == null
	getSingleton(OrderServiceImpl, () -> createBean(OrderServiceImpl, mbd, args)) {
		// 标记 OrderServiceImpl 为初始化状态
		beforeSingletonCreation(OrderServiceImpl)
		// 创建对象,并且完成属性赋值
		singletonObject = singletonFactory.getObject() -> createBean(OrderServiceImpl, mbd, args) >>> doCreateBean(OrderServiceImpl, mbdToUse, args) {
			// 使用反射技术,实例化对象
			instanceWrapper = createBeanInstance(OrderServiceImpl, mbd, args);
			// OrderServiceImpl 是单例 && 允许循环依赖 && 当前bean为初始化状态
			if (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(OrderServiceImpl)){
				// OrderServiceImpl 工厂类加到准备实例化的objectFactory集合中
				addSingletonFactory(OrderServiceImpl, () -> getEarlyBeanReference(OrderServiceImpl, mbd, bean))
			}
			// 属性赋值
			populateBean(OrderServiceImpl, mbd, instanceWrapper) >>> ... >>> getBean(UserServiceImpl)  >>> doGetBean(UserServiceImpl, null, null, false) {
				getSingleton(UserServiceImpl) == null
				getSingleton(UserServiceImpl, () -> createBean(UserServiceImpl, mbd, args)) {
					// 标记 UserServiceImpl 为初始化状态
					beforeSingletonCreation(UserServiceImpl)
					// 创建对象,并且完成属性赋值
					singletonObject = singletonFactory.getObject() -> createBean(UserServiceImpl, mbd, args) >>> doCreateBean(UserServiceImpl, mbdToUse, args) {
						// 使用反射技术,实例化 UserServiceImpl
						instanceWrapper2 = createBeanInstance(UserServiceImpl, mbd, args);
						// UserServiceImpl 是单例 && 允许循环依赖 && 当前bean为初始化状态
						if (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(UserServiceImpl)){
							// UserServiceImpl 工厂类加到准备实例化的objectFactory集合中
							addSingletonFactory(UserServiceImpl, () -> getEarlyBeanReference(UserServiceImpl, mbd, bean))
						}
						// 属性赋值
						populateBean(UserServiceImpl, mbd, instanceWrapper2) >>> ... >>> getBean(OrderServiceImpl) >>> doGetBean(OrderServiceImpl, null, null, false) {
							getSingleton(OrderServiceImpl) == OrderServiceImpl
						}
						// 执行bean的各种init方法+执行前后置处理器
						exposedObject = initializeBean(UserServiceImpl, exposedObject, mbd);
						return instanceWrapper2;
					}
					// 移除当前bean的初始化状态
					afterSingletonCreation(beanName)
					// 加入缓存
					addSingleton(beanName, singletonObject)
				}
			}
			// 执行bean的各种init方法+执行前后置处理器
			exposedObject = initializeBean(OrderServiceImpl, exposedObject, mbd);
			return instanceWrapper;
		}
		// 移除当前bean的初始化状态
		afterSingletonCreation(beanName)
		// 加入缓存
		addSingleton(beanName, singletonObject)
	}
}

其实Spring的内部是形成了递归调用的循环算法。就是getBean()方法中,执行各种操作之后,又走回getBean() 方法。

为什么需要使用三级Map缓存解决循环依赖问题

讲道理只需要2层既可以解决循环依赖的问题了

  1. 标记当前bean正在初始化(用singletonsCurrentlyInCreation
  2. 第一层map(singletonObjects)获取完全体的bean?没有继续执行
  3. 第二层map(earlySingletonObjects)获取仅初始化bean?没有继续执行
  4. 直接将实例放进二级map,并返回实例

需要使用三级Map singletonFactories的场景是为了解决AOP对象注入到容器中的bean是代理类,而不是当前对象

https://my.oschina.net/u/4340310/blog/4332450

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值