刚才看了手机上的公众号,看到一个问题,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的话就不行了。