高频面试题-说清楚Spring如何解决循环依赖?

简介: Spring的循环依赖问题一直是中高级Java高频面试题之一,其中的考点就在于你对Spring中bean的加载过程是否有一定的理解。

Spring的循环依赖问题一直是中高级Java高频面试题之一,其中的考点就在于你对Spring中bean的加载过程是否有一定的理解。


那么我们就以下几点说一下。


Spring中常用的注入方式有哪几种?

构造器注入

set方法注入

注解注入


关于这方面的知识之后再细聊,今天重点不是这些。


什么是循环依赖?

循环依赖,注意,这里说的是依赖,而不是调用,这是两个概念,一定不要混淆。


循环依赖从字面意思来看,就是A依赖B,然后B依赖A,当然,这个依赖过程也可以更长,不一定就非要两个互相依赖,十个八个也是循环依赖,只要形成了一个闭环。


image.png

如图,这样就形成了一个闭环,简单说,如此依赖下去,就是一个死循环。


如何解决循环依赖?


Spring中的循环依赖包括两种,构造器循环依赖和setter循环依赖。


构造器循环依赖


当使用构造器注入方式时,Spring是无法解决循环依赖的,在出问题时会报错,抛出BeanCurrentlyInCreationException异常。


模拟一下场景的话,大概如下:


1. X1在创建时,发现构造器需要X2类对象,只能去创建X2;


2. X2在创建时,又发现构造器需要X3类对象,只能去创建X3;


3. X3在创建时,又再次发现构造器需要X1对象;周而复始,最终抛出异常。


setter循环依赖


主要来说一下setter循环依赖,通过Spring在创建bean时的一级、二级、三级缓存的概念解决的。


注意:这里解决的只是单例模式下的setter循环依赖,非单例模式下的依然没有办法解决,在业务环境中应当尽量避免此类情况。


创建Bean的缓存概念:


一级缓存:singletonObjects,可以称为成品池,存放完全实例化属性赋值完成的Bean,直接可以使用。


二级缓存:earlySingletonObjects,可以称为半成品池,存放早期Bean的引用,尚未属性装配的Bean


三级缓存:singletonFactories,可以称为工厂池,存放实例化完成的Bean工厂。

image.png


通过setter注入时,会经历以下几个过程。

image.png

看图说话!


1. X1在创建时,首先根据构造函数创建bean,暴露一个Factory给三级缓存(工厂池),并且将其放入二级缓存(半成品池);然后进行属性的装配,发现有依赖关系,查询三级缓存是否存在,如没有,前往创建。


2. 创建X2时,同X1,前往创建X3。


3. 创建X3时,这时三级缓存中已经存在X1,即可直接注入,然后将X3的bean对象放入一级缓存(成品池)。


4. 随后X2、X1依次可以创建完成,并且放入一级缓存中。


5. 如此就完成setter循环依赖问题的解决,核心就是这个三级缓存。


注意:这里的bean对象创建完成,放入一级缓存中时,会将对应的二级、三级缓存清掉。


目录
相关文章
|
8月前
|
监控 安全 Java
解决 Spring Boot 中 SecurityConfig 循环依赖问题的详解
本文详细解析了在 Spring Boot 中配置 `SecurityConfig` 时可能遇到的循环依赖问题。通过分析错误日志与代码,指出问题根源在于 `SecurityConfig` 类中不当的依赖注入方式。文章提供了多种解决方案:移除 `configureGlobal` 方法、定义 `DaoAuthenticationProvider` Bean、使用构造函数注入以及分离配置类等。此外,还讨论了 `@Lazy` 注解和允许循环引用的临时手段,并强调重构以避免循环依赖的重要性。通过合理设计 Bean 依赖关系,可确保应用稳定启动并提升代码可维护性。
665 0
|
9月前
|
Java Maven 微服务
微服务——SpringBoot使用归纳——Spring Boot集成 Swagger2 展现在线接口文档——Swagger2 的 maven 依赖
在项目中使用Swagger2工具时,需导入Maven依赖。尽管官方最高版本为2.8.0,但其展示效果不够理想且稳定性欠佳。实际开发中常用2.2.2版本,因其稳定且界面友好。以下是围绕2.2.2版本的Maven依赖配置,包括`springfox-swagger2`和`springfox-swagger-ui`两个模块。
397 0
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
365 2
|
9月前
|
缓存 Java 应用服务中间件
微服务——SpringBoot使用归纳——Spring Boot集成Thymeleaf模板引擎——依赖导入和Thymeleaf相关配置
在Spring Boot中使用Thymeleaf模板,需引入依赖`spring-boot-starter-thymeleaf`,并在HTML页面标签中声明`xmlns:th="http://www.thymeleaf.org"`。此外,Thymeleaf默认开启页面缓存,开发时建议关闭缓存以实时查看更新效果,配置方式为`spring.thymeleaf.cache: false`。这可避免因缓存导致页面未及时刷新的问题。
384 0
|
缓存 架构师 Java
图解 Spring 循环依赖,一文吃透!
Spring 循环依赖如何解决,是大厂面试高频,本文详细解析,建议收藏。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
图解 Spring 循环依赖,一文吃透!
|
Java 关系型数据库 数据库
京东面试:聊聊Spring事务?Spring事务的10种失效场景?加入型传播和嵌套型传播有什么区别?
45岁老架构师尼恩分享了Spring事务的核心知识点,包括事务的两种管理方式(编程式和声明式)、@Transactional注解的五大属性(transactionManager、propagation、isolation、timeout、readOnly、rollbackFor)、事务的七种传播行为、事务隔离级别及其与数据库隔离级别的关系,以及Spring事务的10种失效场景。尼恩还强调了面试中如何给出高质量答案,推荐阅读《尼恩Java面试宝典PDF》以提升面试表现。更多技术资料可在公众号【技术自由圈】获取。
|
存储 缓存 Java
Spring面试必问:手写Spring IoC 循环依赖底层源码剖析
在Spring框架中,IoC(Inversion of Control,控制反转)是一个核心概念,它允许容器管理对象的生命周期和依赖关系。然而,在实际应用中,我们可能会遇到对象间的循环依赖问题。本文将深入探讨Spring如何解决IoC中的循环依赖问题,并通过手写源码的方式,让你对其底层原理有一个全新的认识。
293 2
|
设计模式 缓存 Java
面试题:谈谈Spring用到了哪些设计模式?
面试题:谈谈Spring用到了哪些设计模式?
172 2
|
缓存 Java Spring
源码解读:Spring如何解决构造器注入的循环依赖?
本文详细探讨了Spring框架中的循环依赖问题,包括构造器注入和字段注入两种情况,并重点分析了构造器注入循环依赖的解决方案。文章通过具体示例展示了循环依赖的错误信息及常见场景,提出了三种解决方法:重构代码、使用字段依赖注入以及使用`@Lazy`注解。其中,`@Lazy`注解通过延迟初始化和动态代理机制有效解决了循环依赖问题。作者建议优先使用`@Lazy`注解,并提供了详细的源码解析和调试截图,帮助读者深入理解其实现机制。
808 1
|
缓存 Java Spring
手写Spring Ioc 循环依赖底层源码剖析
在Spring框架中,IoC(控制反转)是一个核心特性,它通过依赖注入(DI)实现了对象间的解耦。然而,在实际开发中,循环依赖是一个常见的问题。
153 4