- AbstractApplicationContext.refresh()方法中finishBeanFactoryInitialization(beanFactory)方法,是核心方法。
- 先在缓存中获得实例,调用getSingleton(beanName)方法,缓存中获取不到实例,则调用getSingleton(beanName, () -> {});方法
- 先在一级缓存中拿
- 一级缓存中拿不到再在二级缓存中拿
- 二级缓存中没有则在三级缓存中拿取,这里拿到的是ObjectFactory对象,这里调用BeanPostProcessor接口,获取提前暴露的bean实例,singletonObject并升级为二级缓存
- 如果缓存中拿不到实例,则创建实例,调用beforeSingletonCreation(beanName);beanName存入singletonsCurrentlyCreation容器
- 调用creatBean方法
- 调用createBeanInstance(beanName, mbd, args), 无参构造函数实例化
- addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); 设置三级缓存
- ioc di 依赖注入 populateBean(beanName, mbd, instanceWrapper);,这里会触发依赖属性的getBean操作。
- 实例化操作完成后调用afterSingletonCreation(beanName);方法,此方法把singletonsCurrentlyInCreation要删除该bean,表示实例化完成。
- 最后调用addSingleton方法,存入一级缓存,删除二级、三级缓存。
循环依赖步骤:
1、A 类无参构造函数实例化后,设置三级缓存
2、A 类populateBean 进行依赖注入,这里触发了B 类属性的getBean 操作
3、B 类无参构造函数实例化后,设置三级缓存
4、B 类populateBean 进行依赖注入,这里触发了A 类属性的getBean 操作
5、A 类之前正在实例化,singletonsCurrentlyInCreation 集合中有已经
有这个A 类了,三级缓存里面也有了,所以这时候是从三级缓存中拿到的提前暴露的
A 实例,该实例还没有进行B 类属性的依赖注入的,B 类属性为空。
6、B 类拿到了A 的提前暴露实例注入到A 类属性中了
7、B 类实例化已经完成,B 类的实例化是由A 类实例化中B 属性的依赖注入触发
的getBean 操作进行的,现在B 已经实例化,所以A 类中B 属性就可以完成依赖注
入了,这时候A 类B 属性已经有值了
8、B 类A 属性指向的就是A 类实例堆空间,所以这时候B 类A 属性也会有值了。
--------------------------
面试官:“为什么要使用三级缓存呢?二级缓存能解决循环依赖吗?”
答:如果要使用二级缓存解决循环依赖,意味着所有Bean在实例化后就要完成AOP代理,这样违背了Spring设计的原则,Spring在设计之初就是通过AnnotationAwareAspectJAutoProxyCreator这个后置处理器来在Bean生命周期的最后一步来完成AOP代理,而不是在实例化后就立马进行AOP代理。