idea无法加载spring依赖_Spring源码循环依赖(附25张调试截图)

本文深入探讨Spring如何处理注解属性和构造器注入时的循环依赖问题,通过分析源码展示了Spring在不同注入方式下的处理策略,包括三级缓存机制和依赖检查。通过实例调试,揭示了Spring如何在属性注入时避免循环依赖,而在构造器注入时抛出异常。
摘要由CSDN通过智能技术生成

Spring 在哪些情况下会出现循环依赖错误?哪些情况下能自身解决循环依赖,又是如何解决的?本文将介绍笔者通过本地调试 Spring 源码来观察循环依赖的过程。

1. 注解属性注入

首先本地准备好一份 Spring 源码,笔者是从 Github 上 Clone 下来的一份,然后用 IDEA 导入,再创建一个 module 用于存放调试的代码。

bff3296217973b7f5398f9932214f500.png
调试模块目录

本次调试有三个类,A、B 通过注解 @Autowired 标注在属性上构成循环依赖,Main 为主函数类。

@Component("A")
public class A {
 @Autowired
 B b;
}
@Component("B")
public class B {
 @Autowired
 A a;
}
public class Main {
    
 public static void main(String[] args) {
  ApplicationContext context =
    new ClassPathXmlApplicationContext("spring-config.xml");
  A a = (A) context.getBean("A");
  B b = (B) context.getBean("B");
 }
}

可以先试着运行下,并不会报错,说明这种情况下的循环依赖能由 Spring 解决。

我们要观察如何解决循环依赖,首先需要知道 @Autowired 标注的属性是如何注入的,如 B 是怎么注入到 A 中的。

由于 A、B 的 scope 是 single,且默认 non-lazy,所以在 ClassPathXmlApplicationContext 初始化时会预先加载 A、B,并完成实例化、属性赋值、初始化等步骤。ClassPathXmlApplicationContext 的构造方法如下:

54d5203c6cf2dcdec6835092177e876b.png
ClassPathXmlApplicationContext的构造方法

其中 refresh 是容器的启动方法,点进去,然后找到我们需要的那一步,即实例化 A、B 的步骤:

1bc0945891ed2ad508a87ec55e0920ad.png
refresh方法

finishBeanFactoryInitialization 会先完成工厂的实例化,然后在最后一步实例化 A、B:

8501c2441609800a8fcddb8549981544.png
finishBeanFactoryInitialization

preInstantiateSingletons 将依次对 non-lazy singleton 依次实例化,其中就有 A、B:

ace24ba30945c6960bf58c10d5ddbc05.png
preInstantiateSingletions

A、B 不是工厂类,则直接通过 getBean 触发初始化。首先会触发 A 的初始化。

getBean =&

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值