Spring:SpringIOC循环依赖问题

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

一、什么是循环依赖

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

注意,这里不是函数的循环调用,是对象的相互依赖关系。循环调用其实就是一个死循环,除非有终结条件。

Spring中循环依赖场景有:

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

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

二、循环依赖处理机制

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

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

AbstractBeanFactory.doGetBean()方法:

在获取bean之前如果这个原型bean正在被创建则直接抛出异常。原型bean在创建之前会进行标记这个beanName正在被创建,等创建结束之后会删除标记。

总结:Spring 不支持原型 bean 的循环依赖。

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

Spring 的循环依赖的理论依据基于 Java 的引用传递,当获得对象的引用时,对象的属性是可以延后设置的,但是构造器必须是在获取引用之前。

Spring通过setXxx或者@Autowired方法解决循环依赖其实是通过提前暴露一个ObjectFactory对象来完成的,简单来说ClassA在调用构造器完成对象初始化之后,在调用ClassA的setClassB方法之前就把ClassA实例化的对象通过ObjectFactory提前暴露到Spring容器中。

  • Spring容器初始化ClassA通过构造器初始化对象后提前暴露到Spring容器。
  • ClassA调用setClassB方法,Spring首先尝试从容器中获取ClassB,此时ClassB不存在Spring容器中。
  • Spring容器初始化ClassB,同时也会将ClassB提前暴露到Spring容器中。
  • classB调用setClassA方法,Spring从容器中获取ClassA ,因为第一步中已经提前暴露了ClassA,因此可以获取到ClassA实例。
  • ClassA通过spring容器获取到ClassB,完成了对象初始化操作。
  • 这样ClassA和ClassB都完成了对象初始化操作,解决了循环依赖问题。
责任编辑:武晓燕 来源: 今日头条
相关推荐

2019-11-26 14:30:20

Spring循环依赖Java

2023-11-28 08:00:00

SpringJava

2021-09-01 11:45:10

Spring循环依赖面试

2021-05-06 07:58:57

Spring BeanIOCAOP

2021-10-21 08:31:31

Spring循环依赖面试

2020-02-10 15:50:18

Spring循环依赖Java

2019-09-09 06:30:06

Springboot程序员开发

2023-10-07 08:40:57

缓存属性Spring

2020-05-07 10:05:58

Spring循环依赖Java

2020-07-29 10:40:21

Spring循环依赖Java

2021-06-25 09:47:59

Spring循环依赖Java

2020-09-03 11:04:20

Spring 循环依赖

2024-03-04 08:47:17

Spring框架AOP

2020-12-29 08:34:08

spring循环依赖开发

2022-08-17 07:52:31

Spring循环依赖单例池

2024-03-18 00:00:00

SpringBean设计

2021-03-02 09:45:07

java循环依赖开发技术

2023-09-26 07:49:11

AOP代理spring

2023-05-06 10:23:38

Spring循环强依赖,

2023-05-03 23:48:24

Spring容器初始化
点赞
收藏

51CTO技术栈公众号