spring 循环依赖注入实现原理(源码分析)

本文介绍了Spring中单例模式下循环依赖的解决方案,通过源码分析展示了如何处理A依赖B、B依赖A的情况。在实例化过程中,Spring将对象存入缓存,避免重复创建,从而解决循环依赖问题。
摘要由CSDN通过智能技术生成

结论

只有单例模式下的循环依赖才可以,其他模式会报错。

对循环依赖的简单介绍

A依赖B、B依赖A 形成一个依赖环。spring的解决方案是,实例化A,之后将A封装到一个ObjectFactory对象中存储。对A进行属性填充的时候,发现有B需要实例化,则去实例化B,实例化B的时候也会将B封装到一个ObjectFactory对象中存储。B实例化完之后,会去填充B的属性,这是发现有A属性需要填充,这是不再会去创建A而是从封装了A对象的ObjectFactory中直接取。从而完成B的属性填充,继而完成了A的属性填充。

源码分析

本次源码分析中案例是UrlServiceUrlService2相互依赖。系统首先实例化UrlService,再实例化UrlService2。仔细观察截图可见下面的截图有两次处理依赖处理。我们的本篇的原码也是以下图的方法压栈顺序依次分析。分析者需要有对spring的源码整体有一定的把握,可以参考我的另外两篇文章

在这里插入图片描述
下面进行代码分析篇。

	#AbstractBeanFactory 
	protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
   
			    ...省略
				// 创建bean的入口
				if (mbd.isSingleton()) {
   
					sharedInstance = getSingleton(beanName, () -> {
   
						try {
   
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
   
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
		       return (T) bean;
	}
# DefaultSingletonBeanRegistry
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
   
	//省略
	singletonObject = singletonFactory.getObject(); //实际进入上个代码块的createBean(beanName, mbd, args)方法
	//省略
}
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring循环依赖是指两个或多个Bean之间相互依赖,形成一个循环引用的关系。在Spring容器启动的过程中,如果存在循环依赖,那么默认情况下会抛出BeanCurrentlyInCreationException异常。 下面是Spring循环依赖的源码分析: 1. 当我们向Spring容器中注入一个Bean时,Spring会先检查这个Bean是否已经正在创建中(正在创建的Bean是无法注入的),如果正在创建中,则直接返回一个早期引用,否则继续创建Bean。 2. 在Bean的创建过程中,当遇到依赖注入(如@Autowired注解)时,Spring会检查要注入的Bean是否已经在创建中。如果是,则返回一个代理对象作为占位符,等待真正的Bean创建完毕后再进行注入。 3. Spring使用三级缓存来解决循环依赖问题。第一级缓存是单例池,存放已经创建好的单例Bean。第二级缓存是提前暴露的ObjectFactory,存放早期引用。第三级缓存是用于存放正在创建中的Bean的缓存,用于检测循环依赖。 4. 当检测到循环依赖时,Spring会尝试使用构造函数的方式完成循环依赖。它会先创建一个空对象,并将其放入到第三级缓存中。然后调用构造函数去创建这个Bean,此时依赖的Bean会返回一个早期引用。最后,将这个Bean加入到第一级缓存中,并开始注入依赖。 5. 当所有的Bean都创建完成后,Spring会触发后置处理器的回调方法,完成Bean的初始化。 总结:Spring循环依赖通过使用三级缓存和构造函数来解决,在Bean创建过程中动态地判断和处理循环依赖关系,确保所有的Bean都能被正确地创建和注入
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值