【 手撕Java源码专栏 】深入理解Spring三级缓存:从源码到实践,彻底解决循环依赖

蓮花仙者
发布: 2025-12-03 09:54:07
原创
727人浏览过

示例代码地址:[github](https://github.com/whltaoin/blog-code-collection) **前言**:\u003e 本文将从spring三级缓存的设计原理出发,通过手写实现和详细分析,带你彻底理解spring如何优雅地解决bean循环依赖问题,同时提供常见面试题解析。\u003e

## 一、什么是循环依赖?为什么需要解决它?### 1.1 循环依赖的概念循环依赖是指在应用程序中,多个Bean之间互相依赖,形成一个闭环。最常见的场景如:

```java// A依赖B@Servicepublic class ServiceA { @Autowired private ServiceB serviceB;}

// B依赖A@Servicepublic class ServiceB { @Autowired private ServiceA serviceA;}```

如果没有特殊处理,这种依赖关系会导致无限递归创建Bean,最终导致溢出错误。

立即学习Java免费学习笔记(深入)”;

### 1.2 循环依赖的三种情况在Spring中,循环依赖主要有三种情况:

1. **构造器循环依赖**:通过构造函数注入形成的循环依赖(Spring无法解决)2. **setter方法循环依赖**:通过setter方法注入形成的循环依赖(Spring可以解决)3. **字段注入循环依赖**:通过@Autowired注解直接注入字段(Spring可以解决)

## 二、Spring三级缓存的设计思路### 2.1 为什么需要三级缓存?想象一下这个场景:

+ 我们需要创建Bean A,但它依赖于Bean B+ 我们需要创建Bean B,但它又依赖于Bean A

如果我们能在Bean完全初始化之前,就将它的\"早期引用\"暴露出去,让其他Bean能够引用它,那么就能打破这个循环。

Spring的三级缓存正是基于这个思路设计的。

### 2.2 三级缓存的定义Spring使用三个不同级别的缓存来管理Bean的创建过程:

| 缓存级别 | 名称 | 用途 | 存储内容 || --- | --- | --- | --- || 一级缓存 | singletonObjects | 存储完全初始化好的单例Bean | 已完成所有属性注入和初始化的最终Bean实例 || 二级缓存 | earlySingletonObjects | 存储早期暴露的Bean引用 | 已实例化但尚未完成属性注入的Bean实例 || 三级缓存 | singletonFactories | 存储Bean工厂对象 | 用于创建Bean早期引用的ObjectFactory |

### 2.3 核心设计思想1. **提前暴露引用**:在Bean实例化后、属性注入前,就将其引用暴露出去2. **延迟代理创建**:通过工厂模式,在真正需要时才创建代理对象3. **缓存升级机制**:随着Bean初始化的推进,引用会在不同级别缓存间移动

## 三、手撕Spring三级缓存源码接下来,让我们手动实现一个简化版的Spring三级缓存机制,看看它是如何解决循环依赖的。

### 3.1 定义对象工厂接口首先,我们需要一个对象工厂接口,用于创建Bean的早期引用:

```java/** * 对象工厂接口,用于创建Bean的早期引用 */public interface CustomObjectFactory\u003cT\u003e { /** * 获取Bean实例 * @return Bean实例 */ T getObject();}```

这是Spring中`ObjectFactory`的简化版,它的作用是**在需要时创建或获取对象**,支持延迟初始化。

### 3.2 实现三级缓存核心类下面是我们手动实现的三级缓存核心类,模拟Spring的`DefaultSingletonBeanRegistry`:

```java/** * 自定义单例Bean注册表,实现Spring的三级缓存机制 */public class CustomSingletonBeanRegistry { // 一级缓存:存储完全初始化好的单例Bean private final Map\u003cString, Object\u003e singletonObjects = new ConcurrentHashMap\u003c\u003e(256); // 二级缓存:存储早期曝光的Bean实例(尚未完成属性注入) private final Map\u003cString, Object\u003e earlySingletonObjects = new HashMap\u003c\u003e(16); // 三级缓存:存储Bean工厂对象,用于生成Bean的早期引用 private final Map\u003cString, CustomObjectFactory\u003c?\u003e\u003e singletonFactories = new HashMap\u003c\u003e(16); // 正在创建中的Bean集合 private final Set\u003cString\u003e singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap\u003c\u003e(16)); // 已注册的Bean名称集合 private final Set\u003cString\u003e registeredSingletons = Collections.newSetFromMap(new ConcurrentHashMap\u003c\u003e(256)); // 排除检查的Bean名称集合 private final Set\u003cString\u003e inCreationCheckExclusions = Collections.newSetFromMap(new ConcurrentHashMap\u003c\u003e(16)); /** * 获取单例Bean(核心方法) */ @SuppressWarnings(\"unchecked\") public Object getSingleton(String beanName) { // 1. 先从一级缓存获取 Object singletonObject = this.singletonObjects.get(beanName); // 2. 如果一级缓存中不存在,且当前Bean正在创建中 if (singletonObject == null \u0026\u0026 isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { // 3. 从二级缓存获取早期引用 singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null) { // 4. 从三级缓存获取工厂对象 CustomObjectFactory\u003c?\u003e singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { // 5. 通过工厂获取早期Bean引用 singletonObject = singletonFactory.getObject(); // 6. 将早期引用放入二级缓存 this.earlySingletonObjects.put(beanName, singletonObject); // 7. 从三级缓存移除工厂对象 this.singletonFactories.remove(beanName); } } } } return singletonObject; } /** * 注册单例Bean(完全初始化后的Bean) */ public void registerSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { // 放入一级缓存 this.singletonObjects.put(beanName, singletonObject); // 从二级缓存移除 this.earlySingletonObjects.remove(beanName); // 从三级缓存移除 this.singletonFactories.remove(beanName); // 注册Bean名称 this.registeredSingletons.add(beanName); } } /** * 添加单例工厂(用于创建早期引用) */ public void addSingletonFactory(String beanName, CustomObjectFactory\u003c?\u003e singletonFactory) { synchronized (this.singletonObjects) { // 只有当一级缓存中不存在时,才添加到三级缓存 if (!this.singletonObjects.containsKey(beanName)) { this.singletonFactories.put(beanName, singletonFactory); this.earlySingletonObjects.remove(beanName); } } } /** * 标记Bean为正在创建中 */ public void beforeSingletonCreation(String beanName) { if (!this.inCreationCheckExclusions.contains(beanName) \u0026\u0026 !this.singletonsCurrentlyInCreation.add(beanName)) { throw new RuntimeException(\"Bean with name '\" + beanName + \"' is currently in creation: \" + \"Is there an unresolvable circular reference?\"); } } /** * 标记Bean创建完成 */ public void afterSingletonCreation(String beanName) { if (!this.inCreationCheckExclusions.contains(beanName) \u0026\u0026 !this.singletonsCurrentlyInCreation.remove(beanName)) { throw new RuntimeException(\"Singleton '\" + beanName + \"' isn't currently in creation\"); } } /** * 检查Bean是否正在创建中 */ public boolean isSingletonCurrentlyInCreation(String beanName) { return this.singletonsCurrentlyInCreation.contains(beanName); }}```

这个类实现了Spring三级缓存的核心逻辑,特别是`getSingleton`方法,它定义了从缓存中获取Bean的优先级顺序。

### 3.3 实现Bean工厂接下来,我们实现一个简单的Bean工厂,用于创建和管理Bean:

```java/** * 自定义Bean工厂,用于创建和管理Bean */public class CustomBeanFactory { // 使用我们的自定义单例Bean注册表 private final CustomSingletonBeanRegistry singletonRegistry = new CustomSingletonBeanRegistry(); // 存储Bean定义的映射 private final Map\u003cString, BeanDefinition\u003c?\u003e\u003e beanDefinitions = new HashMap\u003c\u003e(); /** * 注册Bean定义 */ public \u003cT\u003e void registerBean(String beanName, Class\u003cT\u003e beanClass, String... dependencies) { BeanDefinition\u003cT\u003e definition = new BeanDefinition\u003c\u003e(beanClass, dependencies); beanDefinitions.put(beanName, definition); } /** * 获取Bean实例(核心方法) */ @SuppressWarnings(\"unchecked\") public \u003cT\u003e T getBean(String beanName) { // 1. 先尝试从单例缓存中获取 Object bean = singletonRegistry.getSingleton(beanName); if (bean != null) { return (T) bean; } // 2. 如果缓存中没有,开始创建Bean BeanDefinition\u003cT\u003e definition = (BeanDefinition\u003cT\u003e) beanDefinitions.get(beanName); if (definition == null) { throw new RuntimeException(\"No bean named '\" + beanName + \"' available\"); } try { // 3. 标记Bean为正在创建中 singletonRegistry.beforeSingletonCreation(beanName); // 4. 创建Bean实例 T instance = createBean(definition); // 5. 添加到三级缓存,用于解决循环依赖 singletonRegistry.addSingletonFactory(beanName, () -\u003e instance); // 6. 注入依赖 injectDependencies(instance, definition); // 7. 初始化Bean initializeBean(instance); // 8. 注册到单例缓存(一级缓存) singletonRegistry.registerSingleton(beanName, instance); return instance; } catch (Exception e) { throw new RuntimeException(\"Error creating bean with name '\" + beanName + \"': \" + e.getMessage(), e); } finally { // 9. 标记Bean创建完成 singletonRegistry.afterSingletonCreation(beanName); } } // 其他辅助方法... private \u003cT\u003e T createBean(BeanDefinition\u003cT\u003e definition) throws Exception { System.out.println(\"Creating bean instance for: \" + definition.getBeanClass().getSimpleName()); return definition.getBeanClass().getDeclaredConstructor().newInstance(); } private \u003cT\u003e void injectDependencies(T instance, BeanDefinition\u003cT\u003e definition) throws Exception { // 简化的依赖注入实现 // 实际Spring中会使用反射查找setter方法或字段 } private \u003cT\u003e void initializeBean(T instance) { System.out.println(\"Initializing bean: \" + instance.getClass().getSimpleName()); } /** * Bean定义内部类 */ private static class BeanDefinition\u003cT\u003e { private final Class\u003cT\u003e beanClass; private final String[] dependencies; public BeanDefinition(Class\u003cT\u003e beanClass, String[] dependencies) { this.beanClass = beanClass; this.dependencies = dependencies; } public Class\u003cT\u003e getBeanClass() { return beanClass; } public String[] getDependencies() { return dependencies; } }}```

这个Bean工厂模拟了Spring创建Bean的核心流程,包括实例化、属性注入和初始化。

## 四、三级缓存解决循环依赖的完整流程现在,让我们通过一个具体的例子,详细说明三级缓存如何解决循环依赖问题。

### 4.1 创建循环依赖的示例Bean我们创建两个互相依赖的Bean类:

```java/** * 示例BeanA,与BeanB形成循环依赖 */public class BeanA { private BeanB beanB; public BeanA() { System.out.println(\"BeanA constructor called\"); } // Setter方法用于依赖注入 public void setBeanB(BeanB beanB) { this.beanB = beanB; System.out.println(\"BeanA injected with BeanB\"); } public String getMessage() { return \"Hello from BeanA\"; }}

/** * 示例BeanB,与BeanA形成循环依赖 */public class BeanB { private BeanA beanA; public BeanB() { System.out.println(\"BeanB constructor called\"); } // Setter方法用于依赖注入 public void setBeanA(BeanA beanA) { this.beanA = beanA; System.out.println(\"BeanB injected with BeanA\"); } public String getMessage() { return \"Hello from BeanB\"; }}```

### 4.2 循环依赖解决的详细流程下面是一个详细的流程图,展示了三级缓存如何解决循环依赖:

```plain┌─────────────┐ ┌─────────────┐ ┌─────────────┐│ 创建BeanA │ │ 创建BeanB │ │ 完成初始化 │└─────┬───────┘ └─────┬───────┘ └─────┬───────┘ │ │ │ ▼ ▼ ▼┌─────────────┐ ┌─────────────┐ ┌─────────────┐│ 1.标记创建中 │ │ 4.标记创建中 │ │ 12.BeanA完成│└─────┬───────┘ └─────┬───────┘ └─────┬───────┘ │ │ │ ▼ ▼ ▼┌─────────────┐ ┌─────────────┐ ┌─────────────┐│ 2.实例化BeanA│ │ 5.实例化BeanB│ │ 13.放入一级 │└─────┬───────┘ └─────┬───────┘ └─────┬───────┘ │ │ │ ▼ ▼ │┌─────────────┐ ┌─────────────┐ ││ 3.放入三级缓存│─────▶7.需要BeanA │ │└─────┬───────┘ └─────┬───────┘ │ │ │ │ ▼ ▼ │┌─────────────┐ ┌─────────────┐ ││ 9.从三级获取│◀────┼8.查找BeanA │ │└─────┬───────┘ └─────┬───────┘ │ │ │ │ ▼ ▼ │┌─────────────┐ ┌─────────────┐ ││10.放入二级缓存│ │11.BeanB完成 │ │└─────┬───────┘ └─────┬───────┘ │ │ │ │ └───────────────────┘ │ │ │ ▼ │ ┌─────────────┐ │ │ 放入一级缓存 │ │ └─────────────┘ │ │ │ └─────────────────────┘```

详细步骤说明:

1. **初始化BeanA**: - 标记BeanA为正在创建中 - 实例化BeanA(调用构造函数) - 将BeanA的工厂对象放入三级缓存 - BeanA需要注入BeanB,开始创建BeanB2. **初始化BeanB**: - 标记BeanB为正在创建中 - 实例化BeanB(调用构造函数) - 将BeanB的工厂对象放入三级缓存 - BeanB需要注入BeanA,触发从缓存获取BeanA3. **解决循环依赖**: - BeanB尝试注入BeanA时,从三级缓存获取BeanA的工厂 - 通过工厂获取BeanA的早期引用,放入二级缓存 - 将BeanA的早期引用注入到BeanB中 - BeanB完成属性注入和初始化,放入一级缓存 - 回到BeanA,注入已经完全初始化的BeanB - BeanA完成所有初始化,放入一级缓存

### 4.3 运行效果展示当我们运行以下测试代码:

```java// 创建自定义Bean工厂CustomBeanFactory beanFactory = new CustomBeanFactory();

// 注册Bean定义,声明循环依赖关系beanFactory.registerBean(\"beanA\", BeanA.class, \"beanB\");beanFactory.registerBean(\"beanB\", BeanB.class, \"beanA\");

// 获取BeanA,这将触发循环依赖的解决过程BeanA beanA = beanFactory.getBean(\"beanA\");```

我们会看到类似这样的输出:

```plainCreating bean instance for: BeanABeanA constructor calledCreating bean instance for: BeanBBeanB constructor calledBeanB injected with BeanAInitializing bean: BeanBBeanA injected with BeanBInitializing bean: BeanA```

这清晰地展示了三级缓存如何解决循环依赖的过程。

## 五、为什么需要三级缓存而不是两级?这是面试中的高频问题。很多人会问:既然二级缓存已经可以存储早期引用,为什么还需要三级缓存?

### 5.1 AOP代理的考虑**答案核心:三级缓存的关键作用是支持AOP代理。**

具体来说:

1. **延迟代理创建**:ObjectFactory允许在真正需要时才创建代理对象,而不是在Bean实例化后立即创建2. **条件代理**:只有当Bean被其他Bean引用且需要代理时,才会通过工厂创建代理对象3. **避免不必要的代理**:如果一个Bean没有被其他Bean循环依赖引用,就不会触发从三级缓存获取

### 5.2 举个例子说明假设我们有一个需要AOP代理的Bean:

Unscreen
Unscreen

AI智能视频背景移除工具

Unscreen 331
查看详情 Unscreen

+ **两级缓存方案**:无论是否有循环依赖,都需要在Bean实例化后立即创建代理对象,放入二级缓存+ **三级缓存方案**:只有当有循环依赖时,才会在真正需要引用时通过工厂创建代理对象

这样,三级缓存避免了不必要的代理对象创建,提高了性能。

## 六、常见面试题解析### 6.1 Spring如何解决循环依赖?**答案**:Spring通过三级缓存机制解决循环依赖问题:

1. **一级缓存(singletonObjects)**:存储完全初始化好的Bean2. **二级缓存(earlySingletonObjects)**:存储早期暴露的Bean引用3. **三级缓存(singletonFactories)**:存储Bean工厂对象

当出现循环依赖时,Spring会在Bean实例化后但未完成属性注入前,将Bean的工厂对象放入三级缓存。当另一个Bean需要依赖该Bean时,会通过工厂获取早期引用,并将其升级到二级缓存,从而解决循环依赖问题。

### 6.2 构造器注入的循环依赖为什么无法解决?**答案**:构造器注入的循环依赖无法解决的原因是:在构造器注入的情况下,Bean在实例化阶段就需要依赖对象完全创建好。当A的构造器需要B,而B的构造器需要A时,就会陷入死循环。

Spring的三级缓存机制只能解决setter注入的循环依赖,因为setter注入允许先创建实例,再注入依赖。

### 6.3 Spring中singletonObjects、earlySingletonObjects和singletonFactories的区别?**答案**:

+ **singletonObjects**:一级缓存,存储完全初始化好的单例Bean,这些Bean已经完成了所有属性注入和初始化过程+ **earlySingletonObjects**:二级缓存,存储早期暴露的Bean引用,这些Bean已经实例化但尚未完成属性注入+ **singletonFactories**:三级缓存,存储Bean工厂对象,用于在需要时创建Bean的早期引用或代理对象

这三个缓存的优先级依次是:singletonObjects \u003e earlySingletonObjects \u003e singletonFactories

### 6.4 如果移除三级缓存,只用两级缓存,能解决循环依赖吗?**答案**:如果不考虑AOP代理,只用两级缓存也可以解决简单的循环依赖。但在有AOP代理的情况下,两级缓存无法正确处理代理对象的创建时机,可能导致获取到的不是最终的代理对象。

三级缓存通过ObjectFactory提供了更灵活的机制,可以在真正需要时才创建代理对象,这对于正确处理AOP代理至关重要。

## 八、手写与原生三级缓存对比测试与分析为了深入理解Spring三级缓存的工作原理,我们不仅分析了源码,还手动实现了一套简化版的三级缓存机制,并通过测试进行了对比。下面我们来看看两种实现的测试结果和对比分析。

### 8.1 测试模块概述我们创建了两个测试类,分别验证Spring原生三级缓存和自定义三级缓存的功能:

1. **SpringThreeLevelCacheTest**:测试Spring框架自带的三级缓存机制2. **CustomThreeLevelCacheTest**:测试我们手写的三级缓存实现

### 8.2 Spring原生三级缓存测试#### 8.2.1 测试类实现```java@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(classes = SpringConfig.class)public class SpringThreeLevelCacheTest { @Autowired private ServiceA serviceA; @Autowired private ServiceB serviceB; @Test public void testCircularDependency() { System.out.println(\"\===== Spring三级缓存循环依赖测试 =====\"); // 验证ServiceA是否成功注入了ServiceB System.out.println(\"ServiceA调用结果: \" + serviceA.getInfo()); // 验证循环依赖是否成功解决 System.out.println(\"验证循环依赖是否解决:\"); System.out.println(\"- ServiceA的serviceB引用: \" + serviceB.getMessage()); // 打印两个对象的hashCode,确认是同一个实例 System.out.println(\"\对象引用验证:\"); System.out.println(\"- ServiceA实例: \" + serviceA); System.out.println(\"- ServiceB实例: \" + serviceB); System.out.println(\"\Spring三级缓存成功解决了循环依赖问题!\"); }}```

#### 8.2.2 被测试的服务类```java@Componentpublic class ServiceA { private ServiceB serviceB; public ServiceA() { System.out.println(\"ServiceA构造函数被调用\"); } @Autowired public void setServiceB(ServiceB serviceB) { System.out.println(\"ServiceA的setServiceB方法被调用\"); this.serviceB = serviceB; } public String getInfo() { return \"ServiceA调用ServiceB: \" + serviceB.getMessage(); }}

@Componentpublic class ServiceB { private ServiceA serviceA; public ServiceB() { System.out.println(\"ServiceB构造函数被调用\"); } @Autowired public void setServiceA(ServiceA serviceA) { System.out.println(\"ServiceB的setServiceA方法被调用\"); this.serviceA = serviceA; } public String getMessage() { return \"Hello from ServiceB\"; }}```

### 8.3 自定义三级缓存测试#### 8.3.1 测试类实现```javapublic class CustomThreeLevelCacheTest { @Test public void testCustomThreeLevelCache() { System.out.println(\"\===== 自定义三级缓存循环依赖测试 =====\"); // 创建自定义Bean工厂 CustomBeanFactory beanFactory = new CustomBeanFactory(); // 注册Bean定义,声明循环依赖关系 beanFactory.registerBean(\"beanA\", BeanA.class, \"beanB\"); beanFactory.registerBean(\"beanB\", BeanB.class, \"beanA\"); System.out.println(\"\开始获取BeanA(触发循环依赖解决过程)...\"); // 获取BeanA,这将触发循环依赖的解决过程 BeanA beanA = beanFactory.getBean(\"beanA\"); // 验证循环依赖解决结果... } @Test public void testDetailedCacheProcess() { // 详细测试三级缓存的工作流程... }}```

#### 8.3.2 核心实现类**CustomSingletonBeanRegistry**:实现三级缓存核心逻辑

```javapublic class CustomSingletonBeanRegistry { // 一级缓存:存储完全初始化好的单例Bean private final Map\u003cString, Object\u003e singletonObjects = new ConcurrentHashMap\u003c\u003e(256); // 二级缓存:存储早期曝光的Bean实例 private final Map\u003cString, Object\u003e earlySingletonObjects = new HashMap\u003c\u003e(16); // 三级缓存:存储Bean工厂对象 private final Map\u003cString, CustomObjectFactory\u003c?\u003e\u003e singletonFactories = new HashMap\u003c\u003e(16); // 获取单例Bean的核心方法 public Object getSingleton(String beanName) { // 1. 先从一级缓存获取 // 2. 如果不存在且Bean正在创建中,从二级缓存获取 // 3. 如果二级缓存也不存在,从三级缓存获取工厂对象 // 4. 通过工厂获取早期引用并升级到二级缓存 } // 其他关键方法:registerSingleton, addSingletonFactory等}```

**CustomBeanFactory**:实现Bean创建和管理

```javapublic class CustomBeanFactory { private final CustomSingletonBeanRegistry singletonRegistry = new CustomSingletonBeanRegistry(); public \u003cT\u003e T getBean(String beanName) { // 1. 先尝试从缓存获取 // 2. 标记Bean为正在创建中 // 3. 创建Bean实例 // 4. 添加到三级缓存 // 5. 注入依赖 // 6. 初始化Bean // 7. 注册到一级缓存 }}```

### 8.4 对比分析结果#### 8.4.1 执行流程对比| 执行阶段 | Spring原生实现 | 自定义实现 || --- | --- | --- || 初始化阶段 | 使用Spring容器和注解 | 手动注册Bean定义 || Bean实例化 | 通过反射和BeanDefinition | 简化的反射创建 || 依赖注入 | 基于Autowired注解和类型匹配 | 基于预先声明的依赖关系 || 循环依赖处理 | 自动使用三级缓存 | 手动实现的三级缓存逻辑 || 执行效率 | 完整但较重 | 简化但高效(示例场景下) |

#### 8.4.2 输出结果对比**Spring原生实现输出:**

```plainServiceA构造函数被调用ServiceB构造函数被调用ServiceB的setServiceA方法被调用ServiceA的setServiceB方法被调用

===== Spring三级缓存循环依赖测试 =====ServiceA调用结果: ServiceA调用ServiceB: Hello from ServiceB验证循环依赖是否解决:- ServiceA的serviceB引用: Hello from ServiceB

对象引用验证:- ServiceA实例: com.example.cache.ServiceA@1a2b3c4d- ServiceB实例: com.example.cache.ServiceB@5e6f7g8h```

☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜

【 手撕Java源码专栏 】深入理解Spring三级缓存:从源码到实践,彻底解决循环依赖

**自定义实现输出:**

```plainBeanA constructor calledBeanB constructor calledBeanB injected with BeanABeanA injected with BeanB

===== 自定义三级缓存循环依赖测试 =====BeanA的消息: Hello from BeanA, using injected BeanBBeanB的消息: Hello from BeanB, using injected BeanA

验证循环引用的一致性:- beanA.getBeanB() == beanB: true- beanB.getBeanA() == beanA: true```

【 手撕Java源码专栏 】深入理解Spring三级缓存:从源码到实践,彻底解决循环依赖

#### 8.4.3 核心差异分析1. **实现复杂度**: - Spring原生实现:非常复杂,有完善的异常处理、事件机制、生命周期回调等 - 自定义实现:简化版本,只保留了核心的三级缓存逻辑2. **扩展性**: - Spring原生实现:高度可扩展,支持各种BeanPostProcessor、FactoryBean等 - 自定义实现:基本无扩展性,仅用于演示三级缓存原理3. **AOP支持**: - Spring原生实现:完整支持AOP代理的创建和应用 - 自定义实现:简化版,未实现完整的AOP代理支持4. **循环依赖处理效果**: - 两种实现都能成功解决setter注入的循环依赖 - 都无法解决构造器注入的循环依赖

### 8.5 实践效果与结论通过这次手写实现和对比测试,我们得到以下重要结论:

1. **三级缓存的核心价值**:通过提前暴露Bean引用,成功打破了循环依赖的死锁2. **实现的灵活性**:Spring的设计允许在不同场景下正确处理各种复杂依赖关系3. **学习价值**:通过手写实现,更深入地理解了Spring框架的内部机制

尽管我们的自定义实现与Spring原生实现有很大差距,但核心的三级缓存思想是一致的,这也证明了Spring设计的精妙之处。

## 九、总结与最佳实践### 9.1 三级缓存核心总结Spring的三级缓存机制是一个精巧的设计,它通过以下方式解决了循环依赖问题:

1. **提前暴露引用**:在Bean完全初始化前就暴露其引用2. **缓存升级机制**:随着Bean初始化的推进,引用在不同级别缓存间移动3. **支持AOP代理**:通过ObjectFactory延迟创建代理对象

### 9.2 实际开发中的最佳实践1. **尽量避免循环依赖**:循环依赖通常表示设计存在问题,应该通过重构消除2. **优先使用构造器注入**:虽然不能解决循环依赖,但更符合面向对象设计原则3. **合理使用@Lazy注解**:可以解决某些构造器注入的循环依赖问题4. **考虑使用接口分离**:将Bean的功能拆分为多个接口,可能有助于消除循环依赖

### 9.3 深入学习的建议1. **阅读Spring源码**:特别是DefaultSingletonBeanRegistry类2. **调试Spring启动过程**:观察Bean的创建和缓存过程3. **尝试自己实现**:像本文一样,手写一个简化版的三级缓存4. **对比测试**:通过对比原生和自定义实现,更深入理解Spring的工作原理

通过本文的介绍和代码实现,相信你已经对Spring三级缓存有了深入的理解。这不仅有助于你在面试中应对相关问题,也能帮助你更好地理解Spring框架的工作原理。

如果你有任何疑问或建议,欢迎在评论区留言讨论!

---

以上就是【 手撕Java源码专栏 】深入理解Spring三级缓存:从源码到实践,彻底解决循环依赖的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号