@Async注解的坑

@Async注解遇上循环依赖,Spring无法解决

场景复现

AService 和 BService 相互引用,AService的 save() 方法加了 @Async 注解。

@Component
public class AService {
    @Resource
    private BService bService;

    @Async
    public void save() {

    }
}

@Component
public class BService {

    @Resource
    private AService aService;

}

这段代码会报BeanCurrentlyInCreationException异常。

将@Async注解去掉之后,再次启动项目,项目成功起来。

问题结论

spring 已经默认解决了循环依赖,但是@Async导致的循环依赖无法解决。

分析

AsyncAnnotationBeanPostProcessor 没有实现 getEarlyBeanReference

它的代理逻辑只在:

org.springframework.aop.framework.AbstractAdvisingBeanPostProcessor#postProcessAfterInitialization

而循环依赖发生在初始化之前(属性注入阶段),此时:

  • A 还没走到 postProcessAfterInitialization

  • B 拿到的是 A 的原始对象(raw bean)

  • 调用 a.asyncMethod()同步执行!代理未生效!

解决办法

1、调整对象间的依赖关系,从根本上杜绝循环依赖,没有循环依赖,就没有早期暴露这么一说,那么就不会出现问题。

2、不使用@Async注解,可以自己通过线程池实现异步,这样没有@Async注解,就不会在最后生成代理对象,也就不会导致跟早期暴露出去的对象不一样。

3、可以在循环依赖注入的字段上加@Lazy注解。

Last updated