diff --git a/source/_posts/2023-11-22-circular-dependencies-in-Spring.md b/source/_posts/2023-11-22-circular-dependencies-in-Spring.md
new file mode 100644
index 00000000..e89b59c8
--- /dev/null
+++ b/source/_posts/2023-11-22-circular-dependencies-in-Spring.md
@@ -0,0 +1,398 @@
+---
+title: Spring 中的循环依赖
+date: 2023-11-22 08:28:26
+tags:
+ - java
+ - spring
+---
+
+## 循环依赖的介绍和讨论
+
+### 什么是循环依赖?
+
+当 bean A 依赖另一个 bean B,bean B 也依赖了 bean A,我们称之为循环依赖:
+
+```console
+Bean A -> bean B -> bean A
+```
+
+首先,我们应该将循环依赖和 Spring 中的循环依赖问题分开看待。循环依赖是一个正常的现象,一个 employee 依赖他的 department,department 拥有许多 employee。先实例化 employee 后实例化 department,然后为它们设置依赖,或者颠倒顺序进行操作,并不会发生什么问题。
+
+### Spring 中的循环依赖问题
+
+当 Spring 加载所有的 beans 时,会进行**依赖注入**处理。Spring 并不是先将所有的 bean 实例化,再去进行依赖注入,而是实例化一个 bean 后,立即对它进行依赖注入,为此它会递归地实例化 bean 的依赖。
+实际上,以上的过程同样并不会产生什么大问题,在**实例化和依赖注入分成两个阶段**的情况下,你可以**轻而易举地保存和获取已经实例化的 bean**。唯一的问题是,获取的已经实例化的 bean 可能尚未初始化完毕(比如依赖尚未全部注入),那么你只需要确保它在初始化完毕前不被使用即可。
+这样你通过两个 map,一个保存已经初始化完毕、可用的完成品 bean,一个保存尚未初始化完毕、不可用的半成品 bean,就能解决问题了。
+
+> 在一些资料中,你会看到有人强调如果只是想要解决常规的循环引用,那么只需要两个缓存。
+
+{% asset_img "Pasted image 20231122210105.png" 循环引用-常规情况的解决方案 %}
+
+但是问题并不总是那么简单,如果实例化和依赖注入不能分为两个阶段,如果 B 依赖的不再是简单的 A 对象,而是 A 的代理,那么上述方案就不再适用了。
+
+#### 构造器方法形成的循环依赖
+
+如果 A 的构造器方法需要 B,B 的构造器方法需要 A,那么在 A 的实例化阶段就需要 B 的实例,B 的实例化阶段又需要 A,这就陷入了死循环。
+
+> 虽然我们常说 Spring 解决了循环依赖问题,但实际上,Spring 并没有解决所有情形的循环依赖问题。
+在构造器方法形成的循环依赖中,需要人为地介入,使用 @Lazy 注解告诉 Spring,延迟初始化 Bean 来解决。
+如果是 prototype 类型的 bean 发生循环依赖,Spring 也会抛出异常。显然每次都创建新的 bean 必然会导致无限循环。
+
+#### 循环依赖中出现代理
+
+Spring 鼎鼎大名的核心功能,除了 IOC,还有 AOP。在 AOP 的场景中,bean A 的完成品不是简单的 A 对象,而是一个 A 的代理。
+
+思路其实并不难,既然需要 A 的代理,那么在获取 B 依赖的 A 时,直接根据已有的半成品 A 创建代理就好了。
+
+#### 解决方案的思路小结
+
+当我们脱离 Spring 具体的代码讨论循环依赖问题,我们会发现解决的思路是简单、清晰和理所当然的。事实上 Spring 的解决方案也是如此。
+
+1. 循环依赖本身是普通的,手动可解决的。
+2. Spring 依赖注入时,虽然 bean B 依赖的 bean A 尚未初始化完毕,但是已经实例化,可以用来赋值
+3. Spring AOP 中,既然 bean B 依赖的 bean A 需要是 A 对象的代理,那么就创建代理,再用来赋值
+
+## 测试用例和流程图预览
+
+{% asset_img "Pasted image 20231122233750.png" 循环引用-流程图 %}
+
+- CircularA
+```java
+public class CircularA {
+ private CircularB circularB;
+ public CircularB getCircularB() {
+ return circularB;
+ }
+ public void setCircularB(CircularB circularB) {
+ this.circularB = circularB;
+ }
+}
+```
+- CircularB
+```java
+public class CircularB {
+ private CircularA circularA;
+ public CircularA getCircularA() {
+ return circularA;
+ }
+ public void setCircularA(CircularA circularA) {
+ this.circularA = circularA;
+ }
+}
+```
+- circular-reference-test.xml
+```xml
+
+
+
+
+
+
+
+
+```
+- 测试类
+```java
+public class CircularReferenceTest {
+ @Test
+ public void testRegular() {
+ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("circular-reference-test.xml");
+ CircularA circularA = (CircularA) applicationContext.getBean("circularA");
+ }
+}
+```
+
+## 第一次获取 circularA
+
+### AbstractBeanFactory#doGetBean(circularA)
+
+1. 从缓存中获取 circularA(先不看具体代码)
+2. 因缓存中不存在,就创建 circularA
+
+```java
+protected T doGetBean(
+ final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly)
+ throws BeansException {
+ // 尝试从缓存中获取 circularA,结果为 null
+ Object sharedInstance = getSingleton(beanName);
+ // ...
+ // 再次从缓存中获取 circularA,如果为 null,就创建
+ sharedInstance = getSingleton(beanName, new ObjectFactory