循环依赖三重境界之一:简单循环依赖
juejin.cn/post/684490…
循环依赖三重境界之二:@EnableAspectJAutoProxy
juejin.cn/post/684490…
循环依赖三重境界之三:@Async
juejin.cn/post/684490…
仍有问题?
经过前面两篇,感觉spring应该是解决了循环依赖问题,但是这一篇就是要来说,有些情况spring还是没有完美解决,那就是@Async异步等。
问题在哪儿
我们在动态代理篇应该能看到,在B中对A进行后置处理,和A中对A进行后置处理,这两个是走的不一样的逻辑,这样就会产生问题。
AnnotationAwareAspectJAutoProxyCreator不会有这个问题,因为首先它实现了SmartInstantiationAwareBeanPostProcessor接口,利用getEarlyBeanReference首先在B中得到A的bean时完成了对A的代理,回到A创建过程中时,在postProcessAfterInitialization方法中发现已经对A进行过代理,因此就不再处理。
也就是说,在非循环依赖中的代理过程,在循环依赖中被转移了,而在非循环依赖中的代理过程被跳过了,这样还是只进行了一次代理。
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
//SmartInstantiationAwareBeanPostProcessor的接口
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
return wrapIfNecessary(bean, beanName, cacheKey);
}
//BeanPostProcessor接口
@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;
}
}
那么,每个后置处理器都像AnnotationAwareAspectJAutoProxyCreator一样这么智能吗? 我们来看看今天的主角AsyncAnnotationBeanPostProcessor
它甚至没有实现SmartInstantiationAwareBeanPostProcessor接口,也就是说,它对循环依赖的处理并不像AnnotationAwareAspectJAutoProxyCreator一样,(其实我们可以发现它的循环依赖有问题),那我们来分析一下AsyncAnnotationBeanPostProcessor的处理过程吧AsyncAnnotationBeanPostProcessor
这里一样需要跳转原图看一看了 www.processon.com/view/link/5…标红的地方就是与AnnotationAwareAspectJAutoProxyCreator不一样的地方。
对于AnnotationAwareAspectJAutoProxyCreator来说,回到A中时,发现已经代理过,便不再代理,去容器拿A的代理对象。
对于AsyncAnnotationBeanPostProcessor来说,回到A中时,对A进行处理,得到A2,并且仍去容器拿A的bean,称为A1。
接下来就是重头戏了
出错啦
从容器中拿的A2 !=null,就拿exposedObject 与 bean进行对比。
bean是什么?
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
exposedObject是什么?
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
对于AnnotationAwareAspectJAutoProxyCreator来说
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
//这里this.earlyProxyReferences包含cacheKey,也就是A,因为A已经在B中被代理过
//所以不会进入if的内容,直接返回bean
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
返回了原来的bean。
对于AsyncAnnotationBeanPostProcessor来说
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (isEligible(bean, beanName)) {
ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);
if (!proxyFactory.isProxyTargetClass()) {
evaluateProxyInterfaces(bean.getClass(), proxyFactory);
}
proxyFactory.addAdvisor(this.advisor);
customizeProxyFactory(proxyFactory);
//做了处理
return proxyFactory.getProxy(getProxyClassLoader());
}
// No proxy needed.
return bean;
}
返回了proxyFactory.getProxy(getProxyClassLoader()),也就是代理后的对象。
回到
我们会发现,进入了else if中,最终会抛出异常,异常的内容意思是说,我们在B中注入的是经过处理的A1,但是现在getBean(A.class)得到的却是另一个经过处理的对象A2。
解决问题
参考
cloud.tencent.com/developer/a… 吧,暂时实在是没精力写了,通宵加班,精神崩溃中。