ABA问题 ,出现循环依赖
SpringBean生命周期主要5个阶段
1. 实例化对象
2. 属性赋值(值的来源是DI)
3. 初始化 (初始化完成就是个Bean)
4. 使用
5. 销毁
Spring扫描到被 @Service 标记的A类后,会创建A对象,A类里的有B对象,那么就说A依赖了B;
因为B上被 @Autowired 标记,Spring又会去解析这个 @Autowired注解,表明需要为b赋值,Spring先试着从缓存获取Bbean,如果缓存有就不会进入SpringBean生命周期,直接返回Bbean并赋予A的属性b,没有就要创建Bbean再赋值给b,这个过程称为依赖注入
A在推断构造完成了A 对象实例化,此时的b=null, 意味b对象里面的方法是不能被调用的,报空指针,A属性赋值都没走完,自然也没有完成初始化,所以我愿称此时A为不完整、不成熟的普通对象,总之A不是Bean。A不成熟不代表属于A的方法不能被使用呀,它只是一个属性 b=null而已,A内部其它不依赖b的方法还是可以的,所以将A放入一个临时X缓存慢慢发育。紧接着进入 属性赋值 阶段
假设Spring没有从缓存中获取Bbean,就会进入依赖注入(DI)创建Bbean,
1.实例化B
2.属性赋值 ----> 取出X缓存中 不成熟的A普通对象 (不成熟,不代表不可用,Spring的循环依赖的理论依据基于Java的引用传递
,当获得对象的引用时,对象的属性是可以延后设置的)
3.初始化
因为B能走到初始化阶段,意味b能称为Bean,
好了问题来了Bbean要缓存在哪里??????
结论: 如果想打破死循环,使用一级缓存就可以,如上图缓存X,红色表示成熟的Bean与早期态Bean共存,坏处就是红色小字,后面新开辟一块缓存装成熟态的Bean,以后使用从Y缓存获取bean就好,貌似很好解决问题了,但是Spring其实使用的3级缓存,为什么?
先弄清楚3级缓存分别存的是什么?
1. 一级缓存(SingletonObjects):成熟态,完整的Bean
2.二级缓存(EarlySingletonObjects):早期态的实例 (解决:重复创建aop-proxy问题)
3. 三级缓存(SingletonFactory):lambda(beanName,Object)函数接口
所以缓存的访问顺序:先132后12
看到上面的步骤,我还是有点不死心,还是想干掉第三级缓存,A不是要aop创建代理对象嘛!我在B依赖注入(属性赋值)时就创建aop动态代理不就好了,是可以,但是不符合spring的生命周期规范,动态代理是在初始化阶段进行的,初始化阶段有个BeanPostProcessor扩展接口