Spring IoC 循环依赖问题

Spring IoC 循环依赖问题

什么是循环依赖

循环依赖其实就是循环引用,也就是两个或者两个以上的 Bean 互相持有对方,最终形成闭环。比如 A 依赖于 B,B 依赖于 C,C 又依赖于 A。
在这里插入图片描述

循环调用其实就是一个死循环,除非有终结条件。

Spring 中循环依赖场景有:

  • 构造器的循环依赖(构造器注入)
  • Field 属性的循环依赖(set注入)

其中,构造器的循环依赖问题无法解决,只能拋出 BeanCurrentlyInCreationException 异常,在解决属性循环依赖时,spring 采用的是提前暴露对象的方法。

循环依赖处理机制

  • 单例 bean 构造器参数循环依赖(无法解决)
  • prototype 原型 bean 循环依赖(无法解决)

对于原型 bean 的初始化过程中不论是通过构造器参数循环依赖还是通过 setXxx 方法产生循环依赖,Spring 都会直接报错处理。

Spring 不支持原型 bean 的循环依赖

进入 AbstractBeanFactory#doGetBean 方法:
在这里插入图片描述
在这里插入图片描述

在获取 bean 之前如果这个原型 bean 正在被创建则直接抛出异常。原型 bean 在创建之前会标记 beanName 正在被创建,等创建结束之后会删除标记。
在这里插入图片描述

单例 bean 通过 setXxx 或者 @Autowired 进行循环依赖

Spring 的循环依赖的理论依据基于 Java 的引用传递,当获得对象的引用时,对象的属性是可以延后设置的,但是构造器必须是在获取引用之前。
Spring 通过 setXxx 或者 @Autowired 方法解决循环依赖其实是通过提前暴露一个 ObjectFactory 对象来完成的。简单来说 ClassA 在调用构造器完成对象初始化之后,在调用 ClassA 的 setClassB 方法之前就把 ClassA 实例化的对象通过 ObjectFactory 提前暴露到 Spring 容器中。
在这里插入图片描述

  • Spring 容器初始化 ClassA 通过构造器初始化对象后提前暴露到 singletonFactories 中。
    在这里插入图片描述

  • ClassA 调用 setClassB 方法,Spring 首先尝试从容器中获取 ClassB,此时 ClassB 不存在 Spring 容器中。

  • Spring 容器初始化 ClassB,同时也会将 ClassB 提前暴露到 singletonFactories 中。ClassB 调用 setClassA 方法,Spring 从 singletonFactories 中获取 ClassA,同时将 ClassA 移到 earlySingletonObjects。至此 ClassB 初始化完毕,并且保存到了单例池中。
    在这里插入图片描述

  • 随着 ClassB 初始化完毕并返回给 ClassA 的创建过程中,ClassA 也完成了对象初始化操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值