其他分享
首页 > 其他分享> > Spring之为什么要用三级缓存

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