简单叙述 Spring 是如何解决循环依赖问题的呢?
文章目录
- 什么是循环依赖?
- 为什么Spring要解决循环依赖?
- Spring是如何解决循环依赖的?
- 具体过程是这样的:
- 结论
- 推荐阅读文章
什么是循环依赖?
首先,我们得知道什么是循环依赖。想象一下,如果有两个小朋友,小明和小红,小明说:“小红是我的好朋友。”然后小红说:“小明也是我的好朋友。”这就是一个简单的循环依赖的例子。在Spring框架中,如果两个或多个bean互相依赖对方,就形成了循环依赖。
为什么Spring要解决循环依赖?
循环依赖可能会导致一些问题,比如在创建bean的时候,如果一个bean还没创建好,另一个依赖它的bean就无法完成创建,这会导致程序无法正常运行。所以,Spring需要一种机制来解决这个问题。
Spring是如何解决循环依赖的?
Spring采用了两种主要的方式来解决循环依赖:
-
三级缓存机制:Spring容器在创建bean的时候,会使用一个三级缓存机制来跟踪bean的创建状态。这个机制包括:
- 一级缓存(singletonObjects):存放已经创建好的单例bean。
- 二级缓存(earlySingletonObjects):存放提前暴露的bean,也就是还没完全创建好的bean。
- 三级缓存(singletonFactories):存放bean工厂对象,用于创建bean。
当Spring尝试创建一个bean时,如果发现这个bean依赖了另一个正在创建的bean,它就会使用三级缓存来解决这个问题。
-
依赖注入时机:Spring有两种依赖注入的方式,一种是构造器注入,另一种是setter注入。对于构造器注入,Spring会确保所有依赖的bean在当前bean创建之前已经创建好。而对于setter注入,Spring会在bean创建后,再注入依赖的bean,这为解决循环依赖提供了可能。
具体过程是这样的:
- 创建bean:当Spring要创建一个bean时,它会先检查这个bean是否已经创建过。
- 检查依赖:如果这个bean依赖了其他bean,Spring会先去创建那些依赖的bean。
- 使用三级缓存:如果依赖的bean也依赖了当前bean,Spring会使用三级缓存来解决这个问题。它会先创建一个半成品bean(即没有完全初始化的bean),然后通过三级缓存提供给依赖它的bean使用。
- 完成bean创建:当所有依赖都解决后,Spring会完成当前bean的创建,并将其放入一级缓存中。
结论
通过这种巧妙的设计,Spring成功地解决了循环依赖的问题,让开发者可以更加方便地构建复杂的应用,而不用担心bean之间的依赖问题。这就是Spring的魔力所在,它让复杂的依赖关系变得简单,让开发者可以更专注于业务逻辑的实现。
推荐阅读文章
- 由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)
- 如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系
- HTTP、HTTPS、Cookie 和 Session 之间的关系
- 什么是 Cookie?简单介绍与使用方法
- 什么是 Session?如何应用?
- 使用 Spring 框架构建 MVC 应用程序:初学者教程
- 有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误
- 如何理解应用 Java 多线程与并发编程?
- 把握Java泛型的艺术:协变、逆变与不可变性一网打尽
- Java Spring 中常用的 @PostConstruct 注解使用总结
- 如何理解线程安全这个概念?
- 理解 Java 桥接方法
- Spring 整合嵌入式 Tomcat 容器
- Tomcat 如何加载 SpringMVC 组件
- “在什么情况下类需要实现 Serializable,什么情况下又不需要(一)?”
- “避免序列化灾难:掌握实现 Serializable 的真相!(二)”
- 如何自定义一个自己的 Spring Boot Starter 组件(从入门到实践)
- 解密 Redis:如何通过 IO 多路复用征服高并发挑战!
- 线程 vs 虚拟线程:深入理解及区别
- 深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别
- 10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!
- “打破重复代码的魔咒:使用 Function 接口在 Java 8 中实现优雅重构!”
- Java 中消除 If-else 技巧总结
- 线程池的核心参数配置(仅供参考)
- 【人工智能】聊聊Transformer,深度学习的一股清流(13)
- Java 枚举的几个常用技巧,你可以试着用用