Spring之为什么要用三级缓存
作者:互联网
刚才看了手机上的公众号,看到一个问题,Spring为什么会有三级缓存,只用两级缓存行不行
结论当然是不行,毕竟做Spring的又不是傻蛋,大师考虑问题那可是很深远的
addSingletonFactory(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { return getEarlyBeanReference(beanName, mbd, bean); } });
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) { Object exposedObject = bean; if (bean != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof SmartInstantiationAwareBeanPostProcessor) { SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName); if (exposedObject == null) { return null; } } } } return exposedObject; }
这里对于一个bean如果应该动态代理就创建代理,如果是普通对象就直接返回普通对象
如果此时有循环依赖,进一步假设这个bean是应该进行动态代理的,那么在B获取A的时候,就会调用这个 getEarlyBeanReference ,并且清除三级缓存,并放入二级缓存
我们再往下看,看 AbstractAutowireCapableBeanFactory.doCreateBean 中的568行
if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference != null) {//如果从一级缓存或二级缓存里取得出来的话,把缓存中的bean返回,保证是同一个对象 if (exposedObject == bean) { exposedObject = earlySingletonReference; }
注意那个false入参
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);//由于入参是false,下面的逻辑不会走,只会在二级缓存里取 if (singletonObject == null && allowEarlyReference) { ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return (singletonObject != NULL_OBJECT ? singletonObject : null); }
如果真的有循环依赖,那么这个bean一定会从三级缓存进入二级缓存,如果这个bean刚好是要被AOP的,那么就一定要保证bean的单例性。所以在最终返回bean之前,检查二级缓存里有没有
该对象,如果有就一定要用缓存里的对象。如果没有循环依赖,那么这个bean肯定在三级缓存里呆着呢,这里由于入参是false。也不会去三级缓存里拿。
结论
只有两级缓存行不行呢?也可能性,不过Spring的逻辑是只有一个完整的bean才会进一级缓存,这个应该是他设计理念问题,或者还有我没有参透的地方
标签:缓存,Spring,beanName,Object,bean,singletonObject,null,三级 来源: https://www.cnblogs.com/juniorMa/p/14087517.html