概述
第一次面试,然后留了一个特别感兴趣的问题,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



那跟完这里,一切都可以解释的通了,加了三级的流程为:

那这样的话,三级缓存都是干嘛的,并且都为了解决什么问题,那就讲透彻了。
当然源码不是贴特别多,因为源码确实挺多的,全贴上来也贴不来,这些都只能自己去看咯。
但是还有个疑问就是,为什么再实例化后不直接判断是否需要代理呢?需要的话直接创建然后存到三级缓存去。不过后来想了想,我觉得估计是因为直接写的话,又麻烦又耦合吧
本文深入探讨Spring框架如何通过三级缓存机制解决循环依赖问题,并解释为何需要三个缓存及涉及AOP代理对象的具体流程。
2614

被折叠的 条评论
为什么被折叠?



