Spring循环依赖

简介: Spring循环依赖

一、正常的bean创建生命周期

  1.   实例化
  2.   属性填充
  3.   初始化前、初始化
  4.   初始化(生成AOP代理对象)
  5.   放入单例池

二、 循环依赖的产生

     创建A对象时需要注入B对象,创建B对象是也要注入A对象

三、解决方式

     spring解决循环的方式是使用了三级缓存:

1. singletonObjects :缓存经过了 完整生命周期 的bean

2. earlySingletonObjects :缓存 未经过完整生命周期的bean ,如果某个bean出现了循环依赖,

就会 提前 把这个暂时未经过完整生命周期的bean放入earlySingletonObjects中,这个bean如果

要经过AOP,那么就会把代理对象放入earlySingletonObjects中,否则就是把原始对象放入

earlySingletonObjects,但是不管怎么样,就是是代理对象,代理对象所代理的原始对象也是

没有经过完整生命周期的,所以放入earlySingletonObjects我们就可以统一认为是 未经过完整

生命周期的bean。

3. singletonFactories :缓存的是一个ObjectFactory,也就是一个Lambda表达式。在每个Bean

的生成过程中,经过 实例化 得到一个原始对象后,都会提前基于原始对象暴露一个Lambda表达

式,并保存到三级缓存中,这个Lambda表达式 可能用到,也可能用不到 ,如果当前Bean没有出

现循环依赖,那么这个Lambda表达式没用,当前bean按照自己的生命周期正常执行,执行完后

直接把当前bean放入singletonObjects中,如果当前bean在依赖注入时发现出现了循环依赖(当前正在创建的bean被其他bean依赖了),则从三级缓存中拿到Lambda表达式,并执行Lambda表达式得到一个对象,并把得到的对象放入二级缓存(如果当前Bean需要AOP,那么执行lambda表达式,得到就是对应的代理对象,如果无需AOP,则直接得到一个原始对象)。

4. 其实还要一个缓存,就是 earlyProxyReferences ,它用来记录某个原始对象是否进行过AOP

了。避免后续AOP被重复执行。

详细过程:

 1. 创建A时,先将A对象名称添加到createset集合中,以标记为A对象正在创建中。

 2. 实例化A,得到一个A对象的 singletonFactories对象,这是一段lamba表达式,只有出现循环依赖时才会执行,得到A的原始对象。

 3. 填充B属性,先去单例池 singletonObjects(一级缓存)中找,没找到去createset集合中找,找到了说明B出现了循环依赖,此时接着去 earlySingletonObjects(二级缓存)中找,如果找不到则去singletonFactories(三级缓存)中找,去singletonFactories(三级缓存)中找实际上是执行最初的那段lamba表达式,得到B的代理对象或者原始对象,放入earlySingletonObjects中。并将对象从三级缓存清除。将B对象赋值给B属性。

 4. 填充其他属性。  

总结:

  1.  解决循环依赖的关键是singletonFactories,它打破了循环依赖的死循环,它只有在出现循环依赖时才执行,返回的是对象的原始对象或代理对象。

  2. earlySingletonObjects最大的作用是保证了在属性注入过程中的单例特性,因为有可能出现C也依赖的A,为了避免在这种情况下又去生成代理对象,就直接去earlySingletonObjects这个缓存中找。

  3. 只有在出现了循环依赖的情况下才会打破Bean生命周期的设 计,如果一个Bean没有出现循环依赖,那么它还是遵守了Bean的生命周期的设计的。

 

相关文章
|
19天前
|
人工智能 Java Spring
Spring Boot循环依赖的症状和解决方案
Spring Boot循环依赖的症状和解决方案
|
1天前
|
Java Spring 缓存
Spring Bean循环依赖详解
【6月更文挑战第2天】
7 2
|
9天前
|
设计模式 Java 开发者
解密Spring:优雅解决依赖循环的神兵利器
解密Spring:优雅解决依赖循环的神兵利器
179 57
|
19天前
|
缓存 Java 开发工具
【spring】如何解决循环依赖
【spring】如何解决循环依赖
132 56
|
19天前
|
存储 缓存 Java
【Spring系列笔记】依赖注入,循环依赖以及三级缓存
依赖注入: 是指通过外部配置,将依赖关系注入到对象中。依赖注入有四种主要方式:构造器注入、setter方法注入、接口注入以及注解注入。其中注解注入在开发中最为常见,因为其使用便捷以及可维护性强;构造器注入为官方推荐,可注入不可变对象以及解决循环依赖问题。本文基于依赖注入方式引出循环依赖以及三层缓存的底层原理,以及代码的实现方式。
28 0
|
19天前
|
存储 缓存 Java
【spring】06 循环依赖的分析与解决
【spring】06 循环依赖的分析与解决
12 1
|
19天前
|
存储 缓存 Java
Spring解决循环依赖
Spring解决循环依赖
|
19天前
|
缓存 算法 Java
开发必懂的Spring循环依赖图解 Spring 循环依赖
开发必懂的Spring循环依赖图解 Spring 循环依赖
26 1
|
19天前
|
Java 应用服务中间件 Maven
SpringBoot 项目瘦身指南
SpringBoot 项目瘦身指南
71 0
|
19天前
|
缓存 安全 Java
Spring Boot 面试题及答案整理,最新面试题
Spring Boot 面试题及答案整理,最新面试题
154 0