Spring解决循环依赖的源码解读

本文深入探讨Spring框架如何通过三级缓存机制解决循环依赖问题,并解释为何需要三个缓存及涉及AOP代理对象的具体流程。

概述

第一次面试,然后留了一个特别感兴趣的问题,spring的解决循环依赖的问题,当时完全想不出来(羞愧),果断后续要去跟一下spring,是如何解决循环依赖的,这样解决有没有其他什么问题,或者有没有解决不了的场景

循环依赖是什么

注:下面的情况,都是基于创建的实例为单例
首先,要理解循环依赖,我们得先了解依赖注入
如有以下代码

@Component
public class Test1 {
   
   @Autowired
   Test2 test2;
   
}

学过spring都知道,上面代码的意思是:将Test1放在Bean容器中,并且创建的单例Test1需要自动注入属性test2,注入的对象为Test2的实例,然后将实例存储在缓存中(DefaultSingletonBeanRegistry.singletonObjects)。简单的流程就类似于这样
在这里插入图片描述

这里要注意,依赖注入对象的时候,其实是需要调用AbstractAutoProxyCreator.wrapIfNecessary生成代理对象的
那如果是下面的代码呢?就会出现问题了


@Component
public class Test1 {

    @Autowired
    Test2 test2;

}

@Component
public class Test2 {
    
    @Autowired
    Test1 test1;
    
}

那这个时候流程就有可能会变成这样:
在这里插入图片描述
此时如果只有一个缓存的话,就变成了循环依赖,死循环了。

解决循环依赖的三级缓存

首先先了解以下三个缓存
在这里插入图片描述
singletonFactories应该是三级缓存才对,因为在getSingleton方法中,调用的第三级别的缓存就是singletonFactories

然后看一下获取对象的调用链:
Context.getBean --> AbstractBeanFactory.dogetBean() --> AbstractBeanFactory.getSingleton(String) -->(缓存中不存在的话) getSingleton(String beanName, ObjectFactory<?> singletonFactory) --> 创建Bean
上面的话主要看两个方法
在这里插入图片描述
在这里插入图片描述
那其实此时流程就可以为这样了:
在这里插入图片描述
那其实又有个问题了,这样一看,只需要两个缓存就可以避免死循环了啊,为什么需要三个缓存?对于这个疑问,查了下资料和代码,发现两层缓存,是满足不了存在Aop代理的情况的。
Aop代理对象
其实在Spring Aop中,其实是有一个ProxyFactory工厂类,是专门用来生成结合了Advisor+原instance的一个proxy代理对象的,这样的话才能实现around/before/after这种切面的功能。
至于aop的代理对象的逻辑,这里就不多说,后续开一篇文章说吧,其实内层也主要是看情况来用jdk和cglib来生成代理而已。

那这个时候有个问题:如果再多了一个代理对象的话,流程就会变成这样:
在这里插入图片描述
但是又想了想,代理对象的创建其实完全可以提前创建,先创建完代理对象之后,存入到第二个缓存(三级缓存),然后后续注入属性的时候直接拿代理对象不就行了吗?然后带着这个疑问去看了下网上的资料以及看了下源码。
网上是这样说的:spring为了避免每次创建代理对象,所以再外面包了一层ObjectFactory,用于后续判断是否有aop操作,如果有的话才创建代理对象,没有的话就不创建
那没办法了,只能跟代码了
首先刚才也说到了doGetBean,第一个对象创建实例其实是AbstractBeanFactory.createBean的,那这个时候我们接着第一个实例创建流程看代码
AbstractBeanFactory.createBean --> AbstractAutowrieCapableBeanFactory.doCreateBean() --> AbstractAutowrieCapableBeanFactory.addSingletonFactory
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
那跟完这里,一切都可以解释的通了,加了三级的流程为:

在这里插入图片描述
那这样的话,三级缓存都是干嘛的,并且都为了解决什么问题,那就讲透彻了。
当然源码不是贴特别多,因为源码确实挺多的,全贴上来也贴不来,这些都只能自己去看咯。
但是还有个疑问就是,为什么再实例化后不直接判断是否需要代理呢?需要的话直接创建然后存到三级缓存去。不过后来想了想,我觉得估计是因为直接写的话,又麻烦又耦合吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值