循环依赖三重境界之三:@Async

3,566 阅读3分钟

循环依赖三重境界之一:简单循环依赖
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… 吧,暂时实在是没精力写了,通宵加班,精神崩溃中。