spring IOC 控制反转
1.创建IOC容器,初始化时会把所有的单例对象创建好put到单例缓存池中(debug调用栈可以查看调用顺序),所有的对象创建过程中,都会把自己的早期对象暴露到三级缓存中
2.针对代理对象时,从三级缓存到二级缓存会经过一次代理,创建完毕之后会删除二级缓存,把单例对象put到缓存池中
3.没有代理对象时,三级缓存还是会到二级缓存,但是不做任何处理
生命周期源码解析
BeanFactory
—> getBean方法
—> doGetBean方法(解析别名、dependsOn依赖属性)
—> getSingleton方法(尝试从三级缓存中获取对象)---> getEarlyBeanReference(经过后置处理器,拿到代理对象,正常bean不会走这步)
—> createBean方法 --->addSingleton方法(bean对象添加到一级缓存)
—> doCreateBean方法
—> createBeanInstance方法(通过反射创建对象到二级缓存)
—> addSingletonFactory方法(暴露早期对象到三级缓存,就是上一步创建的属性还没复制的空壳对象)
—> populateBean方法(给早期对象赋值,发现依赖其他bean,重新开始走一遍getBean流程)
—> bean的后续处理
—> 返回实例化好的对象
看源码的时候发现一个特点,string底层真正有用的方法都是do开头的
spring循环依赖
两个bean互相依赖
一级缓存
一级缓存就是单列缓存池(singletonObjects),用于保存所有的单实例bean(service、controller等单例对象)
二级缓存
用户缓存我们的key为beanName value 是我们的早期对象(代理对象的引用)
三级缓存
该map用户缓存key为beanName value 为objectFactory(包装为早期对象),实例化对象之后会删除三级缓存
代理对象(有事务@Transactional)
原生引用(没有事务)
使用构造函数,循环依赖会有问题:
createBeanInstance方法,构造函数注入已经给属性赋值,永远拿不到空壳对象(早期对象)
springBoot
参考:
哔哩哔哩 (゜-゜)つロ 干杯~-bilibili