Spring中的三级缓存与循环依赖详解
一. 前言
Spring 的三级缓存、循环依赖,我们经常听到这两个词,包括面试也会被面试官问及三级缓存是啥?为啥需要三级缓存?循环依赖是啥?Spring 是如何解决循环依赖的?什么样的循环依赖 Spring 无法解决?
带着上述的问题,我们深入看一下 Spring BeanFactory 的 getBean() 流程;这篇文章需要看官有一定的 Spring 源码了解;
二. 三级缓存是指哪三个
三级缓存其实对应了三个 Map,它是在 DefaultSingletonBeanRegistry 类里作为成员变量的;
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry { /** Cache of singleton factories: bean name to ObjectFactory. */ private Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); /** Cache of early singleton objects: bean name to bean instance. */ private Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16); /** Cache of singleton objects: bean name to bean instance. */ private Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); // ... }
- 三级缓存 singletonFactories:可以看到存的是 ObjectFactory 对象,第三级缓存可以根据对象是否需要创建代理而提前创建出代理对象;或者是创建出普通对象;
- 二级缓存 earlySingletonObjects:顾名思义,它存储的是一个早期对象,存的是半成品对象或者半成品对象的代理对象,用来解决对象创建过程中的循环依赖问题;(这里为什么说是一个半成品对象,因为这里存储的对象的属性可能没有注入完全);
- 一级缓存 singletonObjects:这里存的就是成品对象,实例化和初始化都完成了,我们项目中使用的对象都是在一级缓存中获取的,一级缓存中存放代理对象,普通对象;
三. getBean()流程
我们通过 BeanFactory 的 getBean() 看一下三级缓存的全流程;
直接进入到 AbstractBeanFactory 的 getBean();
// --------------------------- AbstractBeanFactory --------------------------- public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); } // --------------------------- AbstractBeanFactory --------------------------- protected <T> T doGetBean( String name, Class<T> requiredType, Object[] args, boolean typeCheckOnly) { // ... // 我们直接看主流程 // Create bean instance. if (mbd.isSingleton()) { // 这里调用 DefaultSingletonBeanRegistry#getSingleton() // 参数一为 beanName // 参数二为 ObjectFactory 函数式对象 sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } }); beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } // ... }
在 AbstractBeanFactory#doGetBean() 中调用了 DefaultSingletonBeanRegistry#getSingleton(),并且这个 getSingleton() 的参数二是一个 ObjectFactory 函数式对象,这个函数式对象的实现逻辑是 return createBean();
我们先看 DefaultSingletonBeanRegistry#getSingleton();
// ------------------------ DefaultSingletonBeanRegistry ----------------------- public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { synchronized (this.singletonObjects) { // 1. 先从一级缓存中去获取 // 如果获取到了 bean 对象,直接返回 // 没有获取到 bean 对象的话,进入后续创建 bean 对象流程 Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { if (this.singletonsCurrentlyInDestruction) { throw new BeanCreationNotAllowedException(); } // ... try { // 2. 调用 ObjectFactory 对象的 getObject() 创建得到 bean 对象 // 从上述分析我们知道最终实现是 return createBean() // 我们需要看 createBean() 流程 singletonObject = singletonFactory.getObject(); newSingleton = true; } catch (IllegalStateException ex) { singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { throw ex; } } finally { afterSingletonCreation(beanName); } if (newSingleton) { // 3. 创建 bean 成功的情况下 // 将 bean 对象放入到一级缓存 singletonObjects 中 // 并将 beanName 对应的值从二级缓存、三级缓存中移除 addSingleton(beanName, singletonObject); } } return singletonObject; } } // ------------------------ DefaultSingletonBeanRegistry ----------------------- protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { // 将 bean 对象放入一级缓存中 // 并将 beanName 对应的值从二级缓存、三级缓存中移除 this.singletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } }
核心实现是 ObjectFactory 的 createBean(),我们看 createBean() 逻辑;
// --------------------- AbstractAutowireCapableBeanFactory ------------------- protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) { RootBeanDefinition mbdToUse = mbd; // ... try { // 调用 doCreateBean() 创建出 bean 对象,并返回该 bean 对象 Object beanInstance = doCreateBean(beanName, mbdToUse, args); return beanInstance; } catch (Throwable ex) { throw new BeanCreationException(); } } // --------------------- AbstractAutowireCapableBeanFactory ------------------- protected Object doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException { BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { // 1. 实例化对象 // 根据合适的构造方法构造出实例 bean 对象 instanceWrapper = createBeanInstance(beanName, mbd, args); } Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } // 2. 是否应该使用三级缓存,一般情况下都会使用三级缓存 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { // 3. 将 beanName 和对应的函数式对象 ObjectFactory 放入到三级缓存中 // 该 ObjectFactory 已经拿到了刚刚实例化好的 bean 对象,只不过只执行了构造函数 // 该 ObjectFactory 的 getObject() 实现是调用 getEarlyBeanReference() addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // 4. 初始化 Bean 对象 Object exposedObject = bean; try { // 4.1 属性注入 // 如果 A 依赖 B,getBean(A) 时会去调 getBean(B) // 如果 A、B 出现循环依赖,会出现 getBean(A) -> getBean(B) -> getBean(A) 的情况 populateBean(beanName, mbd, instanceWrapper); // 4.2 初始化 bean 对象 // 这里会执行一些 BeanPostProcessor 的后处理方法 // 我们熟悉的 Spring AOP 就是在这里生成的代理类对象的 // 如 @Transactional 使用的后处理器是 AbstractAutoProxyCreator // 如 @Async 使用的后处理器是 AbstractAdvisingBeanPostProcessor // 虽然都是生成 AOP 对象,但是这两者在处理循环依赖时处理逻辑不一样,后面细讲 exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { throw ex; } if (earlySingletonExposure) { // 5. 决定 getBean(A) 是返回 bean 对象还是抛出异常 // 参数二是 false // 从一级缓存或者二级缓存中获取 bean 对象 // 走到这里一般是尝试从二级缓存中获取 bean 对象 // 这里比较绕,我们后面再讲 Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference != null) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<>(); for (String dependentBean : dependentBeans) { if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } if (!actualDependentBeans.isEmpty()) { throw new BeanCurrentlyInCreationException(); } } } } // 6. 注册删除 bean 逻辑 try { registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException(); } // 7. 返回 bean 对象 return exposedObject; }
到此这篇关于Spring三级缓存与循环依赖的文章就介绍到这了,更多相关Spring三级缓存与循环依赖内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
用html css javascript打造自己的RIA图文教程
用html&css&javascript打造自己的RIA之一,包括了配置等2009-07-07基于spring-security 401 403错误自定义处理方案
这篇文章主要介绍了基于spring-security 401 403错误自定义处理方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2021-07-07
最新评论