spring的循环依赖

spring的循环依赖

1 单例 bean 构造器参数循环依赖(⽆法解决)
2 prototype 原型 bean循环依赖(⽆法解决)对于原型bean的初始化过程中不论是通过构造器参数循环依赖还是通过setXxx⽅法产⽣循环依赖,Spring都 会直接报错处理。 总结:S pring 不⽀持原型 bean 的循环依赖。

3 只能解决单例bean通过setXxx或者@Autowired进⾏循环依赖

spring获取bean的顺序是先1级缓存,没有就去2级缓存取,没有3级缓存取

三级缓存是在2.5.4版本才引入的,2.5.4之前的版本都只有一级和三级缓存

一级缓存-singletonObjects是用来存放就绪状态的Bean。保存在该缓存中的Bean所实现Aware子接口的方法已经回调完毕,自定义初始化方法已经执行完毕,也经过BeanPostProcessor实现类的postProcessorBeforeInitialization、postProcessorAfterInitialization方法处理;

二级缓存earlySingletonObjects是用来存放早期曝光的Bean,一般只有处于循环引用状态的Bean才会被保存在该缓存中保存在该缓存中的Bean所实现Aware子接口的方法还未回调,自定义初始化方法未执行,也未经过BeanPostProcessor实现类的postProcessorBeforeInitialization、postProcessorAfterInitialization方法处理。如果启用了Spring AOP,并且处于切点表达式处理范围之内,那么会被增强,即创建其代理对象。

这里额外提一点,普通Bean被增强(JDK动态代理或CGLIB)的时机是在AbstractAutoProxyCreator实现的BeanPostProcessor的postProcessorAfterInitialization方法中,而处于循环引用状态的Bean被增强的时机是在AbstractAutoProxyCreator实现的SmartInstantiationAwareBeanPostProcessor的getEarlyBeanReference方法中。

三级缓存-singletonFactories是用来存放创建用于获取Bean的工厂类-ObjectFactory实例。在IoC容器中, 所有刚被创建出来的Bean,默认都会保存到该缓存中

Bean在这三个缓存之间的流转顺序为(存在循环引用):

通过反射创建Bean实例。是单例Bean,并且IoC容器允许Bean之间循环引用,保存到三级缓存中。
当发生了循环引用时,从三级缓存中取出Bean对应的ObjectFactory实例,调用其getObject方法,来获取早期曝光Bean,从三级缓存中移除,保存到二级缓存中。
Bean初始化完成,生命周期的相关方法执行完毕,保存到一级缓存中,从二级缓存以及三级缓存中移除。
Bean在这三个缓存之间的流转顺序为(没有循环引用):

通过反射创建Bean实例。是单例Bean,并且IoC容器允许Bean之间循环引用,保存到三级缓存中。
Bean初始化完成,生命周期的相关方法执行完毕,保存到一级缓存中,从二级缓存以及三级缓存中移除。
简略流程图:

spring的循环依赖

总结
通过以上分析,我们可以得知Bean在一级缓存、二级缓存、三级缓存中的流转顺序为:三级缓存->二级缓存->一级缓存。但是并不是所有Bean都会经历这个过程,例如对于原型Bean(Prototype),IoC容器不会将其保存到任何一个缓存中的,另外即便是单例Bean(Singleton),如果没有循环引用关系,也不会被保存到二级缓存中的。

参考链接:https://blog.csdn.net/m0_43448868/article/details/113578628

小结

如果没有循环依赖的情况的话,一级缓存就可以搞定所有的情况,只需要在 bean 完全初始化好之后将其放入一级缓存即可。

但是一级缓存解决不了循环依赖的情况,所以,Spring 使用三级缓存来解决了循环依赖问题。

如果使用二级缓存的话,理论上是可行的,但是 Spring 选择了三级缓存来实现,让 bean 的创建流程更加符合常理,更加清晰明了。

相关推荐文档

Spring 为什么要用三级缓存来解决循环依赖问题呢?

原文链接:https://blog.csdn.net/wang489687009/article/details/120655156

Original: https://www.cnblogs.com/leeego-123/p/16077444.html
Author: 不死码农
Title: spring的循环依赖

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/541508/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 记一次base64转MultipartFile的坑

    记一次base64转MultipartFile的坑 现在有个需求是接收base64编码的图片,然后上传到文件服务器上,由于文件服务的代码是固定的代码不能修改,所以只能适配接口。文件…

    Java 2023年6月9日
    0111
  • Linux上安装tomcat

    参考https://www.digitalocean.com/community/tutorials/how-to-install-apache-tomcat-8-on-cento…

    Java 2023年6月14日
    096
  • mybatis-延迟加载

    本文主要介绍下mybatis的延迟加载,从原理上介绍下怎么使用、有什么好处能规避什么问题。延迟加载一般用于级联查询(级联查询可以将主表不能直接查询的数据使用自定义映射规则调用字表来…

    Java 2023年6月9日
    090
  • 简单易懂讲注解

    注解是什么 简单的说,注解就是一种将元数据信息从 xml 剥离开来,然后保存在 java 源代码中,这将使得代码更加清晰易懂,无需维护两个地方: java 源代码以及 xml 配置…

    Java 2023年6月8日
    087
  • Maven基础学习笔记

    Maven基础学习笔记 下载链接 官网:https://maven.apache.org/ 所有版本:https://archive.apache.org/dist/maven/m…

    Java 2023年6月5日
    0107
  • IDEA生成带参数和返回值注释

    步骤说明 打开IDEA进入点击左上角 – 文件 – 设置 – 编辑器 – 活动模板 新建活动模板 填写模板文本 编辑变量 添加变量表…

    Java 2023年6月15日
    0119
  • 虚拟机Tomcat部署javaweb项目

    配置java环境 前言:每个版本的配置方式大同小异,如果有配置过程中有什么问题,多看几篇博客总结实践。 安装jdk8 首先需要删除lcentos自带的openjdk环境 rpm -…

    Java 2023年6月5日
    085
  • 线程的生命周期

    线程的生命周期 线程的生命周期 一、通用的java生命周期 二、线程的方法 1、sleep(long millis)线程休眠 2.wait()线程等待 3、notify()/not…

    Java 2023年6月9日
    085
  • tar、gzip、zip、jar是什么,怎么查看?

    原创:扣钉日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处。 如果你是后端程序员,我想你一定见过 *.tar.gz、 *.zip、 *.jar后缀的文件吧,这些都…

    Java 2023年6月7日
    0106
  • SDOI 2018二轮题解(除Day2T1)

    博主诈尸啦 虽然一轮之后就退役了但是二轮还是要去划划水呀~ 然鹅学了不到一个月文化课再回来看OI的东西有一种恍如隔世的感觉,烤前感觉也没啥可复习的,就补一补去年二轮的题吧。 题目思…

    Java 2023年5月30日
    060
  • 这类注解都不知道,还好意思说会Spring Boot ?

    不知道大家在使用Spring Boot开发的日常中有没有用过 @Conditionalxxx注解,比如 @ConditionalOnMissingBean。相信看过Spring B…

    Java 2023年6月14日
    097
  • Java枚举简单介绍

    枚举 1、枚举简介 枚举,是java中的一种比较特殊的class,它继承了java.lang. Enum类,也就是说在枚举类中是不能够继承其他类的。枚举类型可以取代以往常量的定义方…

    Java 2023年6月13日
    098
  • 邻接表有向图(三)之 Java详解

    邻接表有向图是指通过邻接表表示的有向图。 上面的图G2包含了”A,B,C,D,E,F,G”共7个顶点,而且包含了” 上图右边的矩阵是G2在内存中…

    Java 2023年5月29日
    0116
  • Centos7 上手 Docker 容器及 docker-compose

    卸载旧版本 Docker 较旧的 Docker 版本称为 docker 或 docker-engine 。如果已安装这些程序,请卸载它们以及相关的依赖项。 yum remove d…

    Java 2023年6月7日
    091
  • 设计模式之代理模式

    本文由老王出租房子引出——代理设计模式,将从最简单的静态代理实现开始,后延伸使用jdk实现动态代理,最后扩展到Cglib实现动态代理。为了更深入理解代理模式,我们会对实际应用中的典…

    Java 2023年6月8日
    088
  • 2022-8-16 mysql 第二天 约束

    重点,DQL是我们每天都要接触编写最多也是最难的SQL,该语言用来查询记录,不会修改数据库和表结构。 构建数据库 创建一张student表: DROP TABLE IF EXIST…

    Java 2023年6月13日
    081
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球