上次我们分析了spring bean的创建流程及是怎么解决循环依赖的《springboot ApplicationContext之finishBeanFactoryInitialization(getBean())上》。 但是还留了一个问题:spring可以不要三级缓存吗? 要回答这个问题,还是要回到bean的产生过程,上一篇文章对spring 一个重要的功能Aop没有说明它是怎么实现的。还是一贯的风格,看图说话。 图片说明: ㈡.㈠:2 指的是先选择BeanPostProcessor,然后判断是否是InstantiationAwareBeanPostProcessor类型,再执行 方法2:postProcessAfterInstantiation。
可以看到这里有两个重要的类:BeanPostProcessor、InstantiationAwareBeanPostProcessor会在bean的实例化、初始化过程中调用,其中在实例化后BeanPostProcessor的处理就是Aop实现的地方。
我们知道Aop处理过的类实际上是个代理类(jdk、cglib),不是我们在实例化时产生的类,这就是spring为什么一定要用三级缓存来解决的循环依赖的原因。
我能来看下流程,首先我们定义两个类:
@Service
public class TestA {
@Autowired
private TestB testB;
@Transactional
public void say(){}
}
@Service
public class TestB {
@Autowired
private TestA testA;
}
这样在TestA 在经历实例化、属性赋值、初始化后,InfrastructureAdvisorAutoProxyCreator(别问我为啥是它,要主题明确,下节见分晓)对它进行拦截处理,产生代理类放入到spring容器中,看下如果只是用二级缓存的情况: 如果没有Aop代理,我想二级缓存也是可以的吧。
那我们再来回顾下三级缓存的处理 我们要注意TestA放入的二级缓存的对象是个
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
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;
}
会被 InfrastructureAdvisorAutoProxyCreator中的getEarlyBeanReference拦截处理
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
return wrapIfNecessary(bean, beanName, cacheKey);
}
那它是怎么判断TestA是被代理过二不用重复处理的呢,看下InfrastructureAdvisorAutoProxyCreator的postProcessAfterInitialization
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
spring循环依赖就到这里了吧。
下节继续解释刚才刷流氓的,InfrastructureAdvisorAutoProxyCreator是什么时候加载到spring容器的,有又是怎么产生代理的呢?
|