Spring之为什么要用三级缓存

  刚才看了手机上的公众号,看到一个问题,Spring为什么会有三级缓存,只用两级缓存行不行

  结论当然是不行,毕竟做Spring的又不是傻蛋,大师考虑问题那可是很深远的

  在AbstractAutowireCapableBeanFactory # doCreateBean 方法中,实例化一个bean之后,填充属性值之前,会把该bean放到三级缓存中

addSingletonFactory(beanName, new ObjectFactory<Object>() {
                @Override
                public Object getObject() throws BeansException {
                    return getEarlyBeanReference(beanName, mbd, bean);
                }
            });

  AbstractAutowireCapableBeanFactory # getEarlyBeanReference

  getEarlyBeanReference既是AbstractAutowireCapableBeanFactory 这个BeanFactory的方法名也是

  SmartInstantiationAwareBeanPostProcessor这个beanPostProcessor的方法名

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;
    }

  beanFactory中就是调用每个beanPostProcessor的getEarlyBeanReference

这段代码是中getEarlyBeanReference方法作用是AOP

       AbstractAutoProxyCreator就实现了这个方法

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);
    }

  =============2021-09-02=============

  AbstractAutowireCapableBeanFactory 

    // Initialize the bean instance.
        Object exposedObject = bean;
        try {
            populateBean(beanName, mbd, instanceWrapper);//填充属性,会发生循环依赖 @1
            exposedObject = initializeBean(beanName, exposedObject, mbd);//这里有后置处理器beanPostProcessor,可能会进行aop @2
        }
        catch (Throwable ex) {
            if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
                throw (BeanCreationException) ex;
            }
            else {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
            }
        }

        if (earlySingletonExposure) {
            Object earlySingletonReference = getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {//相等
                    exposedObject = earlySingletonReference;
                }

  再来理一下思路,假设当前正在创建beanA,beanA依赖beanB,beanB也依赖beanA。

  当在实例化BeanA之后,会接着执行populateBean会填充beanB。结果beanB发现自己也需要依赖beanA,此时就会触发三级缓存中的ObjectFactory方法。如果beanA刚好要进行aop,那么在beanB的实例化过程中,由于beanB依赖了beanA,beanA就会提前进行aop,然后将beanA从三级缓存中清掉,再将beanA放入二级缓存。

  在@2处,进行aop之前会判断该beanName是否已经进行过aop,所以这个beanA不会再次被增强。

   Object earlySingletonReference = getSingleton(beanName, false); 第二个参数是false,只会从一级和二级缓存中取。如果beanA被beanB循环依赖,且经过aop,那么beanA肯定在二级缓存。所以 earlySingletonReference != null 为true。

  由于在循环依赖中已经经过了aop,所以 exposedObject == bean 为true

  所以对 exposedObject 赋值,保证最终拿到的bean是经过了aop的beanA。

  

  如果真的有循环依赖,那么这个bean一定会从三级缓存进入二级缓存,如果这个bean刚好是要被AOP的,那么就一定要保证bean的单例性。所以在最终返回bean之前,检查二级缓存里有没有该对象,如果有就一定要用缓存里的对象。如果没有循环依赖,那么这个bean肯定在三级缓存里呆着呢,这里由于入参是false。也不会去三级缓存里拿。

Object earlySingletonReference = getSingleton(beanName, false);

  那么这里earlySingletonReference 就是 null,beanA的值就是开始进行实例化的beanA。

结论

  只有两级缓存行不行呢?没有aop是可以的,有aop的话就不行了。

  

原文地址:https://www.cnblogs.com/juniorMa/p/14087517.html