0%

循环依赖问题

在Spring中,如果一个Bean尝试将自身引用注入到自身中或是多个微服务之间存在循环的引用,Spring会抛出BeanCurrentlyInCreationException异常,这被称为循环依赖问题.
循环依赖问题

1. 循环依赖问题

循环依赖问题通常发生在以下两种场景中:

  • 单例Bean的构造器注入: 当两个或多个单例Bean通过构造器注入彼此时,就会发生循环依赖问题.
  • 原型Bean的循环依赖: 当两个或多个原型Bean之间存在循环依赖时,Spring会创建一个代理对象来解决循环依赖问题.

在初始化A时需要注入B,要注入B就需要创建B实例再初始化B,而在初始B时需要注入A,此时A还没有创建完成就陷入死循环.

1.1. 解决方案

1.1.1. 三级缓存 -> 不存在AOP

Spring通过三级缓存机制来解决单例Bean的循环依赖问题:

  • 一级缓存: 存储完全初始化好的单例Bean.
  • 二级缓存: 存储正在初始化中的单例Bean.
  • 三级缓存: 存储原始的Bean定义,用于解决循环依赖问题.
    创建A时,先生成原始A放入三级缓存,然后依赖B.没有B,所以再创建B,生成原始B放入二级缓存,然后依赖A,将三级缓存的A取到二级缓存,完成B的初始化,将B放入一级缓存.接着完成A的初始化,将A放入一级缓存.
    三级缓存
    虽然过程中原始服务是半成品服务,但是Java是引用传递,拿到了相应服务的引用(也就是内存空间的地址)就行,后续都创建好了,拿到的服务就是完整的.

1.1.2. 设计层面拆分业务逻辑 -> 存在AOP

  • 引入中间服务类,避免A和B互相依赖,例如将A中需要依赖B的逻辑提取出来,放到一个中间服务类中,然后A和B都依赖这个中间服务类.
  • B可能只是用A的简单方法,不去依赖A,而是直接调用A的Mapper.

1.1.3. Lazy注解

使用@Lazy注解来延迟Bean的初始化,直到真正需要使用该Bean时才进行初始化.这可以避免在应用启动时就创建所有的Bean,从而减少循环依赖问题的发生.

欢迎关注我的其它发布渠道

-------------我到底啦 感谢大佬-------------