spring循环依赖为什么要使用三级缓存
回顾下,源码分析:
这里最重要的就在获取三级缓存时候的 getObject().
|
这里获取的是一个 beanFactory,然后具体的执行是下面的代码:
|
这块是在首次创建bean实例(还没有属性注入)时候,放入的。
这里就是去获取最终对象,也就是代理后的对象。
我们看下getEarlyBeanReference是个什么东西?他是一个函数式接口
@FunctionalInterface |
继续分析getEarlyBeanReference,也就是singletonFactory.getObject()到底干了什么
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) { |
这里是将我们的后置处理器再次循环,然后找出SmartInstantiationAware后置处理器,后面都是AOP的操作了。
为什么要使用三级缓存:
1.只一级缓存呢? 当然不行,解决不了循环依赖,会形成死循环。
2. 二级缓存呢? 如果二级缓存里面放入bean对象,能解决循环依赖。只是 解决不了AOP场景下的循环依赖。在AOP情形***入到其他bean的,不是最终的代理对象,而是原始对象。
3. 二级缓存,如果使用现在的三级缓存结构Map<String, ObjectFactory<?>>.里面放入的是现在函数接口,然后调getObject()获取呢?
这样也不行,那么这就不是一个缓存了,每次都会去取。
4.二级缓存,里面直接放入 代理对象呢? 在实例化bean后,调用addSingletonFactory()时候直接放入代理后的对象,如下代码所示:
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) { |
这样完全可行的。
那么为什么spring没这么做呢?Spring 的设计原则是在 Bean 初始化完成之后才延时为其创建代理。
(这个需要回顾AOP原理,创建bean后,在赋值,并且初始化后,会调用后置处理器BeanPostProcessor的postProcessAfterInstantiation()方法.
AbstractAutoProxyCreator实现的postProcessAfterInstantiation()方法.然后创建AOP动态代理)
而三级缓存为了解决循环依赖,不得不提前创建动态代理,而普通的非循环依赖的还是按照bean初始化后创建动态代理,然后放入一级缓存。
下面的图是 动态代理 在非循环 和 循环依赖下 创建时机的对比图