悦书阁 悦书阁
首页
学习笔记
技术文档
idea插件开发
更多
  • 分类
  • 标签
  • 归档

Felix

大道至简 知易行难
首页
学习笔记
技术文档
idea插件开发
更多
  • 分类
  • 标签
  • 归档
  • JVM

  • spring

    • Spring Bean 生命周期:从源码到实战
    • Spring Aop
    • Spring循环依赖
      • 什么是循环依赖
      • 三级缓存
        • singletonObjects(一级缓存:单例池)
        • earlySingletonObjects(二级缓存)
        • singletonFactories(三级缓存)
        • earlyProxyReferences
      • 为什么需要第三级缓存
    • Spring常见问题
  • 并发编程

  • 消息中间件

  • 微服务

  • 三高架构

  • 学习笔记
  • spring
liufei379
2022-06-29
目录

Spring循环依赖

# 什么是循环依赖

什么是循环依赖,如下图所示

A创建时--->依赖B---->B去创建--->依赖A,从而产生了循环

image-20220629104116760

如何解决循环依赖,如下图所示可以引入一个缓存池来解决循环依赖的问题。

image-20220629104648843

从上图可以看出 好像只需要一个缓存(二级缓存)就可以解决循环依赖,那么为什么Spring要设计第三级缓存(singletonFactories)呢。原因是Spring的AOP,如果一个类需要进行AOP生成代理对象,那么存到单例池(singletonObjects)中的就是代理对象,而代理对象是在spring生命周期的初始化后阶段产生的,而赋值属性的步骤是在其之前,那么存入缓存池的就不是代理对象,也就是说给B赋值的A对象不是代理对象,这就与Spring的涉及产生了冲突。

即 B依赖的A和最终的A不是同一个对象。

# 三级缓存

# singletonObjects(一级缓存:单例池)

缓存经过了完整生命周期的bean。

# earlySingletonObjects(二级缓存)

缓存未经过完整生命周期的bean,只要某个bean出现了循环依赖,就会提前把这个暂时未经过完整生命周期的bean放入earlySingletonObjects中(这个bean如果要经过AOP,那么就会把代理对象放入earlySingletonObjects中,否则就是把原始对象放入earlySingletonObjects),即使是代理对象,代理对象所代理的原始对象也是没有经过完整生命周期的。

# singletonFactories(三级缓存)

缓存的是一个Lambda表达式。在每个Bean的生成过程中,经过实例化得到一个原始对象后,都会提前基于原始对象暴露一个Lambda表达式,并保存到三级缓存中(这个Lambda表达式可能用到也可能用不到,如果当前Bean没有出现循环依赖,那么这个Lambda表达式没用)。如果当前bean在依赖注入时发现出现了循环依赖,则从三级缓存中拿到Lambda表达式,并执行Lambda表达式得到一个对象,并把得到的对象放入二级缓存。

# earlyProxyReferences

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

# 为什么需要第三级缓存

主要为了处理AOP的问题。

如果没有第三级缓存earlySingletonObjects,则每个bean在依赖注入之前都要去进行AOP的操作,不符合bean的生命周期步骤设计,即AOP对象是在初始化之后生成。

有第三级缓存,则没有循环依赖的需要AOP对象可以按bean的生命周期步骤进行,有循环依赖的需要AOP对象在依赖注入时通过三级缓存中Lambda表达式获取AOP对象放入二级缓存。初始化后要生成AOP对象时去判断是否已经生成过,已生成则不再处理。

上次更新: 2026/3/11 22:17:56
Spring Aop
Spring常见问题

← Spring Aop Spring常见问题→

最近更新
01
实现idea开发的关键步骤
10-05
02
Redis高可用架构
09-09
03
Zookeeper高可用
08-31
更多文章>
Theme by Vdoing | Copyright © 2022-2026 Felix | 粤ICP备17101757号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式