三级缓存定义
/** Cache of singleton objects: bean name --> bean instance */
/** 一级缓存:用于存放完全初始化好的 bean **/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
/** Cache of early singleton objects: bean name --> bean instance */
/** 二级缓存:存放原始的 bean 对象(尚未填充属性),用于解决循环依赖 */
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
/** Cache of singleton factories: bean name --> ObjectFactory */
/** 三级级缓存:存放 bean 工厂对象,用于解决循环依赖 */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
getBean() 流程
getBean
doGetBean
getSingleton(beanName)
—— 分别从一二三级缓存中查找protected Object getSingleton(String beanName, boolean allowEarlyReference) { // 首先从一级缓存中获取实例 Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { // 一级缓存获取不到 且 正在创建中 synchronized (this.singletonObjects) { // 尝试从二级缓存获取 singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { // 允许循环依赖,则尝试从三级缓存获取 ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { // 回调三级缓存工厂的 getObject(),创建(代理若有必要)bean singletonObject = singletonFactory.getObject(); // 存入二级缓存,删除三级缓存 this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return (singletonObject !=NULL_OBJECT? singletonObject : null); }
注意会调用三级缓存中的
singletonFactory = this.singletonFactories.get(beanName)
返回
singletonFactory.getObject()
存入 earlySingletonObjects 缓存,因为三级缓存中的bean不完整,已实例化但还没有进行依赖注入和初始化,所以也称为提早曝光。-
getSingleton
传入创建 bean 的 function,在其内部回调这个 function 创建 beangetSingleton(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { try { return createBean(beanName, mbd, args); }
createBean
resolveBeforeInstantiation //
Give BeanPostProcessors a chance to return a proxy instead of the target bean instance
通过这个接口自定义实现来替换bean自身的实例化,在bean实例化之前就直接返回
InstantiationAwareBeanPostProcessor
-
doCreateBean
createBeanInstance
确定构造方法并完成实例化addSingletonFactory
将getObject function 放入三级缓存,删除二级缓存,这里getEarlyBeanReference
实际上会返回代理对象(如果需要代理)。这里的addSingletonFactory(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { return getEarlyBeanReference(beanName, mbd, bean); }
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(singletonFactory, "Singleton factory must not be null"); synchronized (this.singletonObjects) { if (!this.singletonObjects.containsKey(beanName)) { this.singletonFactories.put(beanName, singletonFactory); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } } }
populateBean
注入依赖,递归 getBean-
initializeBean
invokeAwareMethods
applyBeanPostProcessorsBeforeInitialization
invokeInitMethods
applyBeanPostProcessorsAfterInitialization
调用
postProcessAfterInitialization
生成代理AOP对象
-
addSingleton
实例化完成后,加入一级缓存,同时删掉二三级缓存
问题
一、循环依赖为什么需要三级缓存?
A → B
B → A
实际上A实例化之后放到缓存,在B需要时从缓存取出,同样可以解决循环依赖。
但 Spring 考虑的是在 AOP 存在的情况下,正常情况下 AOP 发生在属性注入后,初始化时。但在循环依赖的case下,如果不用三级缓存提前暴露bean的引用,就会出现A引用B的原始对象,但是B在完成bean的生命周期后被代理类替换了,产生了不一致。
所以 Spring 采用提前暴露 bean 的生成代理的 reference function。若存在循环依赖则会回调这个function,提前生成代理对象;反之则走正常的 AOP 流程。
二、为什么 prototype 不支持循环依赖?
prototype没有缓存,那么 A → B → A … 就会死循环