@Async注解循环依赖的问题
-
@Async注解spring为什么解决不了循环依赖。
- @EnableAsync注解会在容器中生成一个AsyncAnnotationBeanPostProcessor后置处理器和AsyncAnnotationAdvisor切点,该处理器会寻找@Async注解。如果匹配到了会生成一个代理对象。
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()); }
- 在创建的时候,会去判断早期生成的bean和设置属性后生成的bean。发现不一样并且依赖的bean也创建成功了此时spring就会抛出异常。
if (earlySingletonExposure) { //如果在三级缓存取了一次后就会放入二级缓存中 Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference != null) { //如果处理后的bean和早期bean相同执行的逻辑 if (exposedObject == bean) { exposedObject = earlySingletonReference; } //如果不相同 else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length); for (String dependentBean : dependentBeans) { //添加已经创建成功的bean if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } if (!actualDependentBeans.isEmpty()) { //抛出异常代码,这里太多我删除了,源码可以自己看的到 } } } }
所以很好解释假如A类中有@Async注解,B类中没有。A引用了B,B引用了A。此时spring创建A的时候,会为A类中属性赋值此时B还没有初始化需要初始化B,B实例化完成后需要属性赋值A,A早已经实例化完成,放在三级缓存中(就是为了解决循环依赖用的),在三级缓存中取出A属性赋值,B对象初始化完成。此时走到了2的逻辑,A经过属性赋值后,还会经过后置处理会生成一个代理对象,此时B创建完成。所以spring会抛出异常。