Spring的循环依赖

Spring循环依赖

1 循环依赖解决及概述

(1)循环依赖的问题描述和Spring解决流程

@Component
public class A{
	@Autowired
    private B b;
}

@Component
public class B{
    @Autowired
    private A a;
}

循环依赖, 形式如上.

spring按照顺序初始化Bean:

第一步创建A, 构建A的BeanFactory放置在三级缓存中,然后实例化A, 注入属性, 发现A需要B, 在一级二级三级缓存中没有发现B, 开始创建B;

第二步, 创建B, 构建B的BeanFactory放置在三级缓存中, 然后实例化, 注入属性, 发现B需要A, 于是从一级二级缓存寻找A, 无果, 在三级缓存中找到A的BeanFactory, 从中取出 A(或A的代理对象), 然后将A放置在二级缓存中, 将其从三级缓存中删除, B初始化完成, 进入到一级缓存;

第三步, A从一级缓存中获取到初始化完成的B, A也初始化完成, 进入到一级缓存, A 和 B都初始化完成.

需要注意的是:

三级缓存的目的主要是延迟生成代理对象.

正常情况下, Bean的代理对象是在初始化完成后才生成的, 然而, 如果产生了循环依赖, spring出于开发者考虑, 如果对于Bean进行了AOP代理, 那么对于这个Bean的依赖, 开发者也必然是想注入其代理对象的.

因此, 在产生循环依赖的情况下, Bean的代理对象会提前生成, 将该代理对象传递给依赖者.

亦即是说, Bean的代理对象生成可能会有两个时间点.

在第二步中, spring会进行判断, 如果目标对象被代理, 则提前生成代理对象, 否则在对象初始化完成后再生成代理对象.

产生循环依赖的情况下, 被依赖对象的初始化完成需要从三级缓存中**取出BeanFactory中的实例引用, 此时会作一个判断, **判断该实例是否被增强(AOP), 来决定是否返回代理对象(提前生成代理对象).

在不产生循环依赖的情况下,不需要从beanFactory取出, 因此不需要进行该判断, 正常情况下, 在bean初始化完成后,进行代理对象的生成.

二级缓存的目的则是解决多个Bean相互依赖的问题

@Component
public class A{
	@Autowired
	private B b;
	
	@Autowired
	private C c;
}

@Component
public class B{
    @Autowired
    private A a;
}

@Component
public class C{
    @Autowired
    private C c;
}

如上所示, 当B进行初始化后, A被放置在二级缓存中, 等C进行初始化的时候, 从二级缓存中取出.

参考:

Spring是怎么解决循环依赖的? - 简书 (jianshu.com)

Spring三级缓存 - 简书 (jianshu.com)

面试必杀技,讲一讲Spring中的循环依赖 - 程序员DMZ - 博客园 (cnblogs.com)

spring + spring mvc + tomcat 面试题(史上最全) - 疯狂创客圈 - 博客园 (cnblogs.com)

2 关于循环依赖的种类

spirng中注入的方式分为:

  • 基于构造器的注入
  • 基于setter的注入

另外又涉及到Bean的作用域:

  • 单例-singleton
  • 原型-prototype
  • request
  • session
  • globle-session

因此循环依赖可以分为三类:

  • 单例状态下基于setter注入方式的循环依赖
  • 单例状态下基于构造器的注入方式的循环依赖
  • 多例状态下的循环依赖

对于多例状态下的循环依赖,无法解决

基于构造器注入方式的单例循环依赖,可以采用@lazy的方式,延迟加载以解决

spring本身的机制,只能解决基于setter方式注入的单例循环依赖

资料来源

Spring面试题必知必会-循环依赖概览:

https://blog.csdn.net/a745233700/article/details/80959716

Spring循环依赖详解:

https://blog.csdn.net/a745233700/article/details/110914620

posted @   疯一风  阅读(223)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示