spring源码类图
要记住BeanFactory、DefaultListableBeanFactory、AbstractAutowireCapableBeanFactory
容器刷新前准备工作
设置容器的启动时间
设置活跃状态为true
设置关闭状态为false
获取Environment对象,并加载当前系统的属性值到Environment对象中
准备监听器和事件的集合对象,默认为空的集合
spring三级缓存解决循环依赖
循环依赖产生的原因
A对象中初始化B对象,B对象中又初始化A对象,当实例化A对象后发现A中有B,要去实例化B后再去初始化A,这时候A还没有初始化完成。
spring如何解决循环依赖
spring采用三级缓存解决循环依赖,分别用三个Map存储三个级别的缓存
1、三个map中分别存储什么对象
一级缓存:成品
二级缓存:半成品
三级缓存:lambda表达式(getEarlyBeanReference)
2、三个map缓存的查找对象的顺序是什么样的?
先查一级缓存,找不到,找二级缓存,再找不到,找三级缓存
3、如果只有一个map,能否解决循环依赖
不能,如果只有一个map,那么成品对象和半成品对象必须要放在一个map中,而半成品对象是不能够暴露给外部使用的,所以必须要做区分,否则就有可能暴露半成品对象
4、如果只有两个map,能否解决循环依赖问题?
能,但是有前提条件:循环依赖中不包含aop的处理逻辑
doCreateBean
getSingleton
5、为什么三级缓存就可以解决循环依赖中包含代理对象的问题
(1)创建代理对象的时候是否需要创建出原始对象
需要
(2)同一个对象中能否出现同名的两个不同的对象
不能
(3)如果一个被代理对象,那么代理对象跟原始对象应该如何进行存储
如果需要代理对象,那么代理对象创建完成之后应该覆盖原始对象
(4)在之前的某个步骤中,好像出现了覆盖的过程
在getEarlyBeanReference方法中,会判断是否需要代理对象,如果创建出代理对象,那么需要覆盖
(5)在对象对外暴露的时候,如何准确的给出原始对象或者代理对象,因为正常的代理对象的创建是在BeanPostProcessor的后置处理方法中,在解决循环依赖问题的时候还没有执行到那个地方?
所以此时需要lambda表达式了,类似于是一种回调机制,在确定要对外暴露的时候,就唯一性的确定到底是代理对象还是原始对象,这也是为什么不把代理对象直接放到二级缓存中,而是通过三级缓存lambda表达式的方式来执行的原因
就是聊一个时间问题,什么时候需要对外暴露对象,程序没办法确定,所以需要通过lambda的方式,在确定需要对外暴露的时候才执行对象的确定(原始还是代理)
spring是一个跟业务无关的技术框架,它预先预防一些问题,而不是解决所有问题,就更我们写代码的时候异常处理一样,你能预计你判断到的一些问题,但不是所有的异常情况你全部都能解决掉。