广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Spring解决循环依赖问题及三级缓存的作用
  • 609
分享到

Spring解决循环依赖问题及三级缓存的作用

2024-04-02 19:04:59 609人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

目录前言1什么是循环依赖2 如何解决循环依赖3无法解决的循环依赖前言 所谓的三级缓存只是三个可以当作是全局变量的Map,spring的源码中大量使用了这种先将数据放入容器中等使用结束

前言

所谓的三级缓存只是三个可以当作是全局变量的Map,spring源码中大量使用了这种先将数据放入容器中等使用结束再销毁的代码风格

Spring的初始化过程大致有四步:

  • 创建beanFactory,加载配置文件
  • 解析配置文件转化beanDefination,获取到bean的所有属性、依赖及初始化用到的各类处理器等
  • 刷新beanFactory容器,初始化所有单例bean
  • 注册所有的单例bean并返回可用的容器

我们说的循环依赖就是第四步在给Bean属性注入的时候发生的一个问题

1什么是循环依赖

循环依赖就是:

假设有两个类 A和B,A中需要注入B,B中需要注入A
由于A注入B时B没有创建,B创建时A也无法创建导致的死循环问题

2 如何解决循环依赖

我们都知道aop是Spring的一个重要核心思想,其实现就是根据动态代理来实现的,也就是说我们的Bean其实很大概率都是要生成代理类,让我们先来看无代理的情况:

Bean的初始化大概是这样的:

根据以上步骤可以看出bean初始化是一个相当复杂的过程,假如初始化A bean时,发现A bean依赖B bean,即A初始化执行到了第4步填充属性,需要注入B bean,此时B还没有初始化,则需要暂停A,先去初始化B,那么此时new出来的A对象放哪里,直接放在容器Map里显然不合适,半残品怎么能用,所以需要提供一个可以标记创建中bean(A)的Map,可以提前暴露正在创建的bean供其他bean依赖,而如果初始化A所依赖的bean B时,发现B也需要注入一个A的依赖(即发生循环依赖),则B可以从创建中的beanMap中直接获取A对象(创建中)注入A,然后完成B的初始化,返回给正在注入属性的A,最终A也完成初始化,皆大欢喜。

如果没有循环依赖,A 依赖B,就是创建B,B依赖C就去创建C,创建完了逐级返回就行,并不需要什么缓存,所以,一级缓存之后的其他缓存(二三级缓存)就是为了解决循环依赖而设立的
一级缓存其实就是我们的成熟的Bean了,可以直接被使用

我们去看一下源码:

从源码中我们可以看到,三级缓存里放的并不是实例化的Bean,而是一个工厂,这是为什么呢?
循环依赖在实际应用可能会有,但很少,简单的应用场景是: controller注入service,service注入mapper,只有复杂的业务,可能service互相引用,有可能出现循环依赖,所以为了出现循环依赖才去解决,不出现就不解决,虽然支持循环依赖,但是只有在出现循环依赖时才真正暴露早期对象,否则只暴露个获取bean的方法,并没有真正暴露bean,因为这个方法不会被执行到,这块的实现就是三级缓存(singletonFactories),只缓存了一个单例bean工厂
为什么是一个工厂?或者说这个工厂的作用?
三级缓存bean工厂的getObject方式,实际执行的是getEarlyBeanReference,如果对象需要被代理(存在beanPostProcessors -> SmartInstantiationAwareBeanPostProcessor),则提前生成代理对象。

三级缓存已经解决所有问题了,二级缓存用来做什么呢?为什么三级缓存不直接叫做二级缓存?这个应该是在缓存使用时决定的:

此时这个方法中的判断逻辑是:

  • 一级缓存中没有
  • 对象A确实正在创建中
  • 二级缓存中也没有
  • 最终去三级缓存中获取对象,从三级缓存获取后把对象从三级缓存删除然后放入到二级缓存中,由于当初放入到三级缓存中的是一个工厂,所以从三级缓存中拿对象是调用getEarlyBeanReference这个方法获取,这个方法的作用是如果对象需要代理,那么就返回代理类,如果不需要代理就返回原生类,至此属性注入A完成

那么为什么要把对象从三级缓存放到二级缓存呢?

给大家一个循环依赖的流程图,大家一看便知:

看到了吗,如果AB都需要代理,我们在A的属性注入时创建了B,但是此时A还是原生的A,但是我们需要代理A,而代理A在B注入A时已经创建并放入二级缓存中了,我们直接从二级缓存拿然后替换原生A即可。

所以,我理解的是二级缓存是为了应对代理这个情况而生的
至此,循环依赖的问题已经完美解决

3无法解决的循环依赖

构造函数循环依赖:

如果我们的成员属性是在构造函数里呢?
首先要解决循环依赖就是要先实例化然后放入三级缓存暴露出来,那么如果是构造函数这一步循环依赖,
实例化的时候就会产生无限递归创建,所以不能解决

多例的循环依赖:

如果是多例的,在容器初始化的时候,不会去创建,所以早期没有放入到三级缓存中暴露出来,所以无法解决循环依赖,会报错

到此这篇关于Spring解决循环依赖问题及三级缓存的作用的文章就介绍到这了,更多相关Spring解决循环依赖问题内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Spring解决循环依赖问题及三级缓存的作用

本文链接: https://www.lsjlt.com/news/153954.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Spring解决循环依赖问题及三级缓存的作用
    目录前言1什么是循环依赖2 如何解决循环依赖3无法解决的循环依赖前言 所谓的三级缓存只是三个可以当作是全局变量的Map,Spring的源码中大量使用了这种先将数据放入容器中等使用结束...
    99+
    2022-11-13
  • Spring解决循环依赖问题及三级缓存的作用是什么
    本文小编为大家详细介绍“Spring解决循环依赖问题及三级缓存的作用是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“Spring解决循环依赖问题及三级缓存的作用是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知...
    99+
    2023-07-02
  • Spring使用三级缓存解决循环依赖的问题
    Spring如何使用三级缓存解决循环依赖在没开始文章之前首先来了解一下什么是循环依赖 @Component public class A { @Autowired ...
    99+
    2022-11-12
  • Spring三级缓存解决循环依赖
    目录一级缓存为什么不能在实例化A之后就放入Map?二级缓存 二级缓存已然解决了循环依赖问题,为什么还需要三级缓存?三级缓存 源码 我们都知道Spring中的BeanFactory是一...
    99+
    2022-11-12
  • 怎么使用Spring三级缓存解决循环依赖问题
    这篇文章主要介绍了怎么使用Spring三级缓存解决循环依赖问题的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇怎么使用Spring三级缓存解决循环依赖问题文章都会有所收获,下面我们一起来看看吧。循环依赖什么是循环...
    99+
    2023-07-05
  • Spring解决循环依赖的方法(三级缓存)
      说起Spring,作为流水线上装配工的小码农,可能是我们最熟悉不过的一种技术框架。但是对于Spring到底是个什么东西,我猜作为大多数的你可能跟我一样,只知道IOC、DI,却并不...
    99+
    2022-11-12
  • Spring三级缓存解决循环依赖的过程分析
    目录循环依赖解决思路解决流程二个缓存不行?总结循环依赖 什么是循环依赖?很简单,看下方的代码就知晓了 @Service public class A { @Autowired...
    99+
    2023-05-14
    Spring循环依赖 Spring三级缓存解决循环依赖
  • Spring为什么需要三级缓存解决循环依赖
    今天小编给大家分享一下Spring为什么需要三级缓存解决循环依赖的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。bean生命周...
    99+
    2023-06-29
  • 教你Spring如何使用三级缓存解决循环依赖
    一级缓存存放实例化对象 。二级缓存存放已经在内存空间创建好但是还没有给属性赋值的对象。三级缓存存放对象工厂,用来创建提前暴露到bean的对象。 @Service public cla...
    99+
    2022-11-13
  • Spring为何需要三级缓存解决循环依赖详解
    目录前言bean生命周期三级缓存解决循环依赖总结前言 在使用spring框架的日常开发中,bean之间的循环依赖太频繁了,spring已经帮我们去解决循环依赖问题,对我们开发者来说是...
    99+
    2022-11-13
  • Spring源码之循环依赖之三级缓存详解
    目录循环依赖定义三种循环依赖的情况1.构造器循环依赖2.settler循环依赖3.prototype范围的依赖处理三级缓存机制整体分析源码分析面试题总结循环依赖 定义 循环依赖就 循...
    99+
    2022-11-13
  • 你知道怎么用Spring的三级缓存解决循环依赖吗
    目录1. 前言2. Spring Bean的循环依赖3. Spring中三大循环依赖场景演示3.1 构造器注入循环依赖3.2 singleton模式field属性注入循环依...
    99+
    2022-11-13
  • 关于spring循环依赖问题及解决方案
    目录一、三种循环依赖的情况比如几个Bean之间的互相引用 甚至自己“循环”依赖自己二、解决方案如何获取依赖三、解决循环依赖必须要三级缓存吗结论四、无...
    99+
    2022-11-13
  • 关于Java Spring三级缓存和循环依赖的深入理解
    目录一、什么是循环依赖?什么是三级缓存?二、三级缓存如何解决循环依赖?三、使用二级缓存能不能解决循环依赖?一、什么是循环依赖?什么是三级缓存? 【什么是循环依赖】什么是循环依赖很好理...
    99+
    2022-11-12
  • 一篇文章带你理解Java Spring三级缓存和循环依赖
    目录一、什么是循环依赖?什么是三级缓存二、三级缓存如何解决循环依赖?三、使用二级缓存能不能解决循环依赖?总结一、什么是循环依赖?什么是三级缓存 【什么是循环依赖】什么是循环依赖很好理...
    99+
    2022-11-12
  • spring bean的自动注入及循环依赖问题怎么解决
    这篇文章主要介绍了spring bean的自动注入及循环依赖问题怎么解决的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇spring bean的自动注入及循环依赖问题怎么解决文章都会有所收获,下面我们一起来看看吧...
    99+
    2023-07-05
  • Spring处理@Async导致的循环依赖失败问题怎么解决
    本文小编为大家详细介绍“Spring处理@Async导致的循环依赖失败问题怎么解决”,内容详细,步骤清晰,细节处理妥当,希望这篇“Spring处理@Async导致的循环依赖失败问题怎么解决”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入...
    99+
    2023-07-02
  • SpringBoot2.6.x默认禁用循环依赖后的问题解决
    目录一、序言二、问题复原1、代码说明2、错误示例三、问题解决1、粗暴解决2、优雅解决四、小结一、序言 SpringBoot 2.6.x不推荐使用循环依赖,这是一个好消息,Spring...
    99+
    2022-11-13
  • 如何解决SpringBoot2.6.x默认禁用循环依赖后的问题
    这篇文章主要介绍了如何解决SpringBoot2.6.x默认禁用循环依赖后的问题,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。一、序言SpringBoot 2.6.x不推荐使...
    99+
    2023-06-29
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作