“Spring 循环依赖”的版本间的差异

来自姬鸿昌的知识库
跳到导航 跳到搜索
 
(未显示同一用户的7个中间版本)
第22行: 第22行:
  
 
=== 实例化和初始化 ===
 
=== 实例化和初始化 ===
实例化是:A a = new A();
+
实例化是:A a = new A(); 的过程
  
初始化是:在实例化后调用 a.setB();
+
初始化是:在实例化后调用 a.setB(); 的过程
 +
 
 +
=== 三级缓存结构 ===
 +
 
 +
==== 一级缓存 ====
 +
保存已经完成初始化的对象
 +
 
 +
==== 第二季缓存 ====
 +
保存已经完成实例化但还没有完成初始化的对象
 +
 
 +
==== 第三层缓存 ====
 +
保存对象工厂,这里存储的对象工厂用于返回或创建单例的对象,而且会判断这个 bean 是否需要 AOP,如果需要 AOP,则返回这个 bean 的代理对象
 +
 
 +
 
 +
=== 执行过程 ===
 +
 
 +
==== 在没有循环依赖的情况下 ====
 +
类 A 发现它的初始化过程中依赖于类 B 的对象,Spring 会先把已经实例化、但还未完成初始化的类 A 的对象 a 放入二级缓存,然后去创建它依赖的类 B 的对象 b,等 b 完成初始化之后放入一级缓存,然后再注入到对象 a 里面,此时 a 完成了实例化和初始化,最后把 a 从二级缓存中删除并放入一级缓存。
 +
 
 +
==== 在 a 和 b 相互循环依赖的情况下 ====
 +
spring 发现 a 依赖 b,则会把 a 的对象工厂放入三级缓存,b 初始化的时候能从三级缓存拿到 a。
 +
 
 +
如果 a 需要代理,对象工厂会返回 a 的代理对象,如果不需要代理,会返回 a 对象本身。
 +
 
 +
拿到类 a 的对象之后,Spring 会删除三级缓存中类 A 的对象工厂,放入二级缓存,然后分别依次初始化 b 和 a:<syntaxhighlight lang="java">
 +
A a = new A();
 +
B b = new B();
 +
a.setB(b);
 +
</syntaxhighlight>

2024年7月15日 (一) 02:55的最新版本

什么是循环依赖

public class A {
    private B b;
    
    public void setB(B b){
        this.b = b;
    }
}
public class B {
    private A a;

    public void setA(A a){
        this.a = a;
    }
}

首先

在实际开发中应该尽量避免循环依赖

实例化和初始化

实例化是:A a = new A(); 的过程

初始化是:在实例化后调用 a.setB(); 的过程

三级缓存结构

一级缓存

保存已经完成初始化的对象

第二季缓存

保存已经完成实例化但还没有完成初始化的对象

第三层缓存

保存对象工厂,这里存储的对象工厂用于返回或创建单例的对象,而且会判断这个 bean 是否需要 AOP,如果需要 AOP,则返回这个 bean 的代理对象


执行过程

在没有循环依赖的情况下

类 A 发现它的初始化过程中依赖于类 B 的对象,Spring 会先把已经实例化、但还未完成初始化的类 A 的对象 a 放入二级缓存,然后去创建它依赖的类 B 的对象 b,等 b 完成初始化之后放入一级缓存,然后再注入到对象 a 里面,此时 a 完成了实例化和初始化,最后把 a 从二级缓存中删除并放入一级缓存。

在 a 和 b 相互循环依赖的情况下

spring 发现 a 依赖 b,则会把 a 的对象工厂放入三级缓存,b 初始化的时候能从三级缓存拿到 a。

如果 a 需要代理,对象工厂会返回 a 的代理对象,如果不需要代理,会返回 a 对象本身。

拿到类 a 的对象之后,Spring 会删除三级缓存中类 A 的对象工厂,放入二级缓存,然后分别依次初始化 b 和 a:

A a = new A();
B b = new B();
a.setB(b);