结论:
之前已经说过循环依赖,但在不使用aop代理时是不需要三级缓存的,二级缓存也可以实现。那么这次将通过aop代理对象进行实例间的循环依赖来查看三级缓存的使用。
首先来简单看下有aop代理时对象初始化的流程
相较于之前不进行aop时,会在B初始化时多一个流程 即“为A创建代理”。
这样做的目的是为什么呢,为什么不在实例化A的时候创建代理缓存起来,然后在B注入属性时使用呢。
原因是spring原本正常是在初始化时AbstractAutoProxyCreator这个后置处理器中进行aop代理对象的生成的。但是由于循环依赖需要把代理对象提前进行代理。所以对于循环依赖时后置处理器不在进行代理对象的生成。如果在实例化A之后就进行代理,这样违背了Spring设计的原则,Spring在设计之初就是通过AnnotationAwareAspectJAutoProxyCreator这个后置处理器来在Bean生命周期的最后一步来完成AOP代理,而不是在实例化后就立马进行AOP代理。
所以在实例化A时,会将A的单例工厂缓存起来。并在B注入属性时判断是否需要代理,如果需要,就创建代理对象作为B的属性进行填充。
源码解析:
主要查看三级缓存存储单例工厂
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 循环依赖-添加到三级缓存 后续循环依赖 调用getEarlyBeanReference 方法获取实例
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
查看为B创建属性时根据A的单例工厂获取A的代理实例
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
}
}
return exposedObject;
}
将A对象放到 earlyProxyReferences 中,说明提前进行了Aop。
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
//提前aop的bean放到 earlyProxyReferences ,在后置处理器执行时判断 earlyProxyReferences是否存在。
//存在说明已经aop了,无需再后置处理器中进行aop
this.earlyProxyReferences.put(cacheKey, bean);
return wrapIfNecessary(bean, beanName, cacheKey);
}
查看wrapIfNecessary方法
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// advisedBeans表示已经判断过了的bean,false表示此bean不需要进行Aop
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 当前正在创建的Bean不用进行AOP,比如切面Bean
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
// 判断当前bean是否存在匹配的advice,如果存在则要生成一个代理对象
// 此处根据类以及类中的方法去匹配到Interceptor(也就是Advice),然后生成代理对象,代理对象在执行的时候,还会根据当前执行的方法去匹配
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
// advisedBeans记录了某个Bean已经进行过AOP了
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
从源码看,spring是在B填充属性A时,A的单例工厂进行了A实例的代理对象的生成。完成B的初始化后。再完成A的初始化。
在A的初始化后 AbstractAutoProxyCreator这个后置处理器中就不再进行A的代理,而是直接使用生成好的代理进行返回。
源码:
AbstractAutoProxyCreator的后置处理器方法,判断earlyProxyReferences 是否存在
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
//判断是否已经bean是否已经Aop,
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
由以上源码可知。后置处理器不再进行aop。