做装修业务呢有多少网站,聊城手机网站建设公司,网站建设的知识点有哪些,17模板网站Spring 的三级缓存是经典面试题#xff0c;也会看到一些文章讲三级缓存与循环依赖之的关系。那么#xff0c;三级缓存分别存储的什么呢#xff1f;他们的作用又分别是什么#xff1f;
一、一、二级缓存
一级缓存是一个名为 singletonObjects 的 ConcurrentHashMap#x…Spring 的三级缓存是经典面试题也会看到一些文章讲三级缓存与循环依赖之的关系。那么三级缓存分别存储的什么呢他们的作用又分别是什么
一、一、二级缓存
一级缓存是一个名为 singletonObjects 的 ConcurrentHashMap用于存储已经创建完成的 Bean。其作用也是最明显的获取 Bean 时最优先从一级缓存中获取。
二级缓存是一个名为 earlySingletonObjects 的 ConcurrentHashMap用于存储还未创建完成的 Bean。在循环依赖时可以从中预先获取未创建完成的 Bean从而解决循环依赖问题。
二、三级缓存
三级缓存是一个名为 singletonFactories 的 ConcurrentHashMap用于存储创建指定 Bean 的工厂。其作用是为了在 AOP 代理时解决循环依赖。 更具体可以说是为了在 AOP 代理时既解决循环依赖又最大满足 Spring 制定的 Bean 生命周期流程。 是的三级缓存一定程度上说他提前了 Bean 生命周期的流程。 熟悉 Bean 的生命周期可知Bean 初始化是经过了实例化createBeanInstance、属性注入populateBean、后置处理器与生命周期方法initializeBean三个步骤处理最终才得到一个创建完成的 Bean。
在循环依赖时在属性注入populateBean步骤就要解决依赖问题而 AOP 代理是在后置处理器与生命周期方法initializeBean步骤中通过后置处理器实现的。如果严格按照 Bean 的这个生命周期执行依赖注入是无法注入代理之后的对象的。
假设A 和 B 互相依赖A 经过 AOP 代理最终的 Bean 为 Aa 那么严格按照 Bean 的生命周期最终属性注入的结果如下 getBean——取得 A Bean在 doCreateBean 方法中开始创建 Bean 操作。 createBeanInstance——实例化 A Bean。 populateBean——为 A Bean 设置参数并调用 getBean 方法创建 B Bean。 createBeanInstance——实例化 B Bean。 populateBean——为 B Bean 设置参数并调用 getBean 方法获得未构造完全的 A Bean。 initializeBean——为A Bean 执行后置处理器和生命周期方法并完成 AOP 代理获得最终的 Aa Bean。 从上面步骤可以发现B 中注入的是代理之前的 A 对象而实际上需要被注入的是代理之后的 Aa 对象。
要解决上述 AOP 代理的问题其实也很简单只要在 createBeanInstance 步骤中完成 AOP 代理其实一切问题就迎刃而解。但是这并不符合 Bean 的生命周期设定而且循环依赖的场景很少见在实例化时也无法判断这个 Bean 是否被循环依赖了直接将 AOP 代理全部提前执行不合适。
最终Spring 引入了三级缓存在实例化对象之后进行属性注入之前将实现 AOP 代理的步骤封装为 Bean 工厂放进三级缓存。如果这个对象被循环依赖了则使用工厂提前进行 AOP 代理如果没有被循环依赖则这个工厂就不会被使用。
boolean earlySingletonExposure (mbd.isSingleton() this.allowCircularReferences isSingletonCurrentlyInCreation(beanName));
// 是否需要提前暴露
if (earlySingletonExposure) {if (logger.isTraceEnabled()) {logger.trace(Eagerly caching bean beanName to allow for resolving potential circular references);}// 创建bean工厂注入到三级缓存addSingletonFactory(beanName, () - getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject bean;
try {populateBean(beanName, mbd, instanceWrapper);exposedObject initializeBean(beanName, exposedObject, mbd);
}阅读 getEarlyBeanReference 方法逻辑可以看到其中遍历找到了实现了SmartInstantiationAwareBeanPostProcessor 接口的后置处理器并执行了其中的 getEarlyBeanReference 方法提前完成了代理操作获取到了代理后的最终得对象。
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {Object exposedObject bean;if (!mbd.isSynthetic() hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {SmartInstantiationAwareBeanPostProcessor ibp (SmartInstantiationAwareBeanPostProcessor) bp;exposedObject ibp.getEarlyBeanReference(exposedObject, beanName);}}}return exposedObject;
}在获取对象时getEarlyBeanReference 便按三级缓存的顺序执行操作如果在三级缓存中获取到 Bean 工厂则通过工厂获取对象。
protected Object getSingleton(String beanName, boolean allowEarlyReference) {// Quick check for existing instance without full singleton lockObject singletonObject this.singletonObjects.get(beanName);if (singletonObject null isSingletonCurrentlyInCreation(beanName)) {singletonObject this.earlySingletonObjects.get(beanName);if (singletonObject null allowEarlyReference) {synchronized (this.singletonObjects) {// Consistent creation of early reference within full singleton locksingletonObject this.singletonObjects.get(beanName);if (singletonObject null) {singletonObject this.earlySingletonObjects.get(beanName);if (singletonObject null) {ObjectFactory? singletonFactory this.singletonFactories.get(beanName);if (singletonFactory ! null) {singletonObject singletonFactory.getObject();this.earlySingletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);}}}}}}return singletonObject;
}