This commit is contained in:
2025-09-16 15:44:12 +08:00
parent a30edaba95
commit 37aad2f7bc
34 changed files with 174 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -0,0 +1,26 @@
---
title: SpringBoot是如何实现自动配置的
published: 2025-09-15
description: ''
image: ''
tags: ['SpringBoot','Java','自动配置']
category: 'Java > Spring'
draft: false
lang: ''
---
# SpringBoot是如何实现自动配置的
Spring Boot的自动配置是通过 `@EnableAutoConfiguration` 注解来实现的。
这个注解包含 `@Import({AutoConfigurationImportSelector.class})`注解
导入的这两个类会扫描classpath下所有的`META-INF/spring.factories`中的文件根据文件中指定的配置类加载相应的Bean的自动配置。
这些Bean通常会使用 `@ConditionOnClass`,`@ConditionOnMissingBean`,`@ConditionalOnProperty`等注解来控制自动配置的加载条件,例如仅在类路径中存在某个类的时候,才加载某些配置。
![](https://blog.meowrain.cn/api/i/2025/09/16/ip1efv-1.webp)
![](https://blog.meowrain.cn/api/i/2025/09/16/ipewwv-1.webp)
![](https://blog.meowrain.cn/api/i/2025/09/16/iqpz9m-1.webp)
![](https://blog.meowrain.cn/api/i/2025/09/16/iquhuf-1.webp)

View File

@@ -0,0 +1,39 @@
---
title: 什么是循环依赖
published: 2025-09-16
description: ''
image: ''
tags: [Spring,循环依赖,Java]
category: 'Java > Spring'
draft: false
lang: ''
---
# 什么是循环依赖
循环依赖就是指两个或者多个模块,类组件之间互相依赖,形成一个闭环
```java
@Service
public class A {
@Autowired
private B b;
}
@Service
public class B {
@Autowired
private A a;
}
//或者自己依赖自己
@Service
public class A {
@Autowired
private A a;
}
```
就像上面这种情况,就属于循环依赖

View File

@@ -0,0 +1,109 @@
---
title: Spring如何解决循环依赖
published: 2025-09-16
description: ''
image: ''
tags: [Spring,循环依赖,Java]
category: 'Java > Spring'
draft: false
lang: ''
---
# Spring如何解决循环依赖
关键是`提前暴露未完全创建完毕的Bean`
Spring中采用了`三级缓存`解决了循环依赖
![](https://blog.meowrain.cn/api/i/2025/09/16/p86lpo-1.webp)
![](https://blog.meowrain.cn/api/i/2025/09/16/p88uqg-1.webp)
![](https://blog.meowrain.cn/api/i/2025/09/16/p8o5kd-1.webp)
我们拿下面这个例子来讲
```java
@Service
public class A {
@Autowired
private B b;
}
@Service
public class B {
@Autowired
private A a;
}
//或者自己依赖自己
@Service
public class A {
@Autowired
private A a;
}
```
首先要创建Bean A,去一级缓存里面找,发现没有,二级缓存里面找,发现也没有,三级里面也没有
这个时候进入Bean A 的对象创建流程
接下来我们利用反射创建对象A调用其无参构造方法创建一个对象A 的实例并将其包装成ObjectFactory放入三级缓存中。
![](https://blog.meowrain.cn/api/i/2025/09/16/p9xvzy-1.webp)
![](https://blog.meowrain.cn/api/i/2025/09/16/pa0adk-1.webp)
接下来要填充属性
![](https://blog.meowrain.cn/api/i/2025/09/16/pac0j5-1.webp)
因为A对象的属性是B对象
所以现在要开始创建Bean B
到一级二级三级缓存中找B对象发现不存在所以进入B对象的创建流程
依然是通过反射调用B的无参构造方法创建B的实例并将其包装成ObjectFactory放入三级缓存中。
![](https://blog.meowrain.cn/api/i/2025/09/16/pb08w0-1.webp)
接下来要填充B对象的属性就又要进入Bean A的创建流程中再去缓存中查找A对象我们能发现在三级缓存中已经有A的ObjectFactory了
![](https://blog.meowrain.cn/api/i/2025/09/16/pbu2du-1.webp)
![](https://blog.meowrain.cn/api/i/2025/09/16/pc7z5d-1.webp)
可以从源码中看到我们会调用存放在三级缓存中A的ObjectFactory的getObject方法创建单例对象存放在earlySingletonObjects里面二级缓存然后从三级缓存中移除A的ObjectFactory
![](https://blog.meowrain.cn/api/i/2025/09/16/pdc4ej-1.webp)
好的这样的话我们就可以把A填充到B对象需要的属性里面了
![](https://blog.meowrain.cn/api/i/2025/09/16/pde1m5-1.webp)
![](https://blog.meowrain.cn/api/i/2025/09/16/pdwvlu-1.webp)
![](https://blog.meowrain.cn/api/i/2025/09/16/pdzjbq-1.webp)
![](https://blog.meowrain.cn/api/i/2025/09/16/pe21e7-1.webp)
我们看看缓存转移的关键源码
![](https://blog.meowrain.cn/api/i/2025/09/16/pe4gjp-1.webp)
第一步先把B的完整对象放到一级缓存中然后从三级缓存中移除B的ObjectFactory再从二级缓存中移除B当然二级缓存中也没有B接下来完成B的单例注册。这样缓存转移就完成了。
![](https://blog.meowrain.cn/api/i/2025/09/16/pf7oj6-1.webp)
这样就完成了B对象的初始化
![](https://blog.meowrain.cn/api/i/2025/09/16/pfvlkh-1.webp)
但是我们B对象的创建流程是在A对象的填充属性流程里所以会继续A的填充属性流程这个时候再去一级缓存里找B就能找到B了填充B并进行缓存转移移除二级三级缓存中的A对象就可以注入B完成A初始化了
![](https://blog.meowrain.cn/api/i/2025/09/16/pgzg8n-1.webp)
# 三级缓存的作用
为了AOP
![](https://blog.meowrain.cn/api/i/2025/09/16/phhvgv-1.webp)
![](https://blog.meowrain.cn/api/i/2025/09/16/phke37-1.webp)
![](https://blog.meowrain.cn/api/i/2025/09/16/phmmeq-1.webp)
当Spring没有循环依赖的情况下是把普通对象创建好后再生成代理对象Spring也没有办法提前知道对象之间的依赖关系。也不能把每个对象都创建出代理对象来所以就需要把对象包装成objectFactory这个类型通过其中的ObjectFactory对象中的getObject方法获取到生成的代理对象。
![](https://blog.meowrain.cn/api/i/2025/09/16/pitrj2-1.webp)