Spring的三级缓存

斗胆写一篇技术博客,记录今天学习的三级缓存解决循环依赖问题,写的错误的和不好的地方请大家见谅(((φ(◎ロ◎;)φ)))

三级缓存的概念

1. 第一级缓存(Singleton Objects):

  • 存放已经完全初始化好的单例bean.当一个bean被完全创建并初始化后,它会被存储在这里.

2. 第二级缓存(Early Singleton Objects):

  • 存放原始的bean对象,即已经实例化但还没有完全初始化的bean.当Spring容器创建一个bean并注入了所有依赖项后,但还未调用afterPropertiesSet()方法或init-method时,bean会被存放在这里.

3. 第三级缓存(Singleton Factories):

  • 存放ObjectFactory,即bean创建工厂(用于创建早期对象).当Spring容器创建bean的实例时,但还未进行属性填充(依赖注入)之前,会先存放一个bean工厂在第三级缓存中.

循环依赖解决过程详解:

  1. Bean A 的创建初始化:
    • Spring容器开始创建Bean A.
    • 实例化:容器首先实例化Bean A(new OperationA()),此时它是一个原始的Java对象,不包含任何Spring的代理或增强.
    • 第三级缓存:这个原始对象被包装为一个ObjectFactory,并存入第三级缓存(SingletonFactories).
  2. Bean A 请求 Bean B:
    • 在Bean A的属性填充过程中,Spring容器发现Bean A需要依赖Bean B.
    • Bean B 创建:容器开始创建Bean B,同样先实例化Bean B.
  3. Bean B 请求 Bean A:
    • 类似于Bean A,Bean B在属性填充时需要依赖Bean A.
    • 早期引用:由于Bean A尚未完全初始化,Spring容器从第三级缓存中取出Bean A的ObjectFactory.
    • 第二级缓存:调用ObjectFactory得到Bean A的早期引用(一个尚未填充属性的Bean A实例),并将其存入第二级缓存(EarlySingletonObjects).
  4. Bean B 依赖注入 Bean A:
    • 将Bean A的早期引用注入到Bean B中.
    • Bean B 初始化:Bean B完成属性填充,执行afterPropertiesSet或自定义的初始化方法,然后从第二级缓存移动到第一级缓存(SingletonObjects).
  5. Bean B 完成创建:
    • Bean B现在是一个完全初始化的单例对象,可以从第一级缓存中获取.
  6. Bean A 依赖注入 Bean B:
    • 回到Bean A的创建过程,Spring容器从第一级缓存中获取完全初始化的Bean B.
  7. Bean A 完成属性填充:
    • Bean A的所有属性(包括注入的Bean B)都已填充完毕.
  8. Bean A 初始化:
    • 执行Bean A的afterPropertiesSet或自定义的初始化方法.
  9. Bean A 完成创建:
    • Bean A从第二级缓存移动到第一级缓存,现在是一个完全初始化的单例对象.
  10. Bean A 和 B 都可用:
    • 至此,Bean A和Bean B都完全创建并初始化,可以被应用程序使用.
  • 概念区分:
    • 实例化对象:指的是Java的new操作创建的对象,此时对象尚未经过Spring容器的任何处理.
    • 早期对象:指的是已经实例化但还未完全初始化的bean,它存在于第二级缓存中.
    • 完全初始化对象:指的是已经完成所有属性填充和初始化方法调用的bean,存在于第一级缓存中.
    • 对象工厂(ObjectFactory):是一个能够创建bean实例的工厂,存在于第三级缓存中,用于在循环依赖中提前暴露bean的早期引用.
    • 实例工厂(Instance Factory):通常指的是Spring容器内部用于创建bean实例的逻辑,这里可以认为是ObjectFactory的具体实现.

通过以上方式,就通过引入三级缓存,解决了循环依赖的问题,在上述流程执行完之后,ServiceA和ServiceB都被成功的完成了实例化和初始化.

欢迎大佬批评指正!

0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
UltramanZero
下载 APP