美文网首页
给一个方法加了@Async注解后,可能就会报有循环依赖的错误,这

给一个方法加了@Async注解后,可能就会报有循环依赖的错误,这

作者: Figo_OU | 来源:发表于2023-11-08 22:44 被阅读0次

给一个方法加了@Async注解后,可能会导致循环依赖错误,这是因为Spring会为这个异步方法创建一个代理对象。代理对象的创建是在Spring容器初始化bean的过程中进行的。当一个bean依赖于另一个bean时,Spring需要按照依赖关系的顺序来初始化bean。如果两个bean之间存在循环依赖关系,那么Spring容器就无法确定它们的初始化顺序,从而导致循环依赖错误。

以两个相互依赖的Service为例:

@Service
public class ServiceA {
    @Autowired
    private ServiceB serviceB;

    @Async
    public void asyncMethodInA() {
        // ...
    }
}

@Service
public class ServiceB {
    @Autowired
    private ServiceA serviceA;
}

在这个例子中,ServiceA依赖于ServiceB,ServiceB依赖于ServiceA。当Spring容器尝试初始化这两个bean时,它需要先初始化ServiceA,然后再初始化ServiceB。但是,因为ServiceA中有一个@Async注解的方法,所以Spring需要为这个方法创建一个代理对象。在创建代理对象的过程中,Spring容器又需要先初始化ServiceB。这就导致了循环依赖错误。

初始化过程:

  1. Spring容器开始初始化ServiceA和ServiceB。
  2. ServiceA依赖于ServiceB,因此Spring容器先尝试初始化ServiceA。
  3. 在初始化ServiceA时,发现ServiceA中有一个@Async注解的方法。因此,Spring容器需要为这个方法创建一个代理对象。
  4. 在创建代理对象的过程中,Spring容器又需要先初始化ServiceB,以便将其注入到ServiceA中。
  5. 但是,ServiceB又依赖于ServiceA,这导致了循环依赖问题,因为Spring容器无法确定这两个bean的初始化顺序。
补充一个代理bean的生成时间 为啥@Async会抛异常
image.png

为了解决这个问题,可以尝试以下方法:

  1. 重新审查和调整bean之间的依赖关系,避免循环依赖。这可以通过重新组织代码结构、调整bean的作用域和生命周期等方式来实现。
  2. 如果确实存在循环依赖,可以考虑将@Async方法移动到一个新的bean中,这样可以避免循环依赖问题。
  3. 使用@Lazy注解来延迟依赖bean的初始化,这样可以在实际使用时再进行初始化,从而避免循环依赖问题。

总之,@Async注解可能会导致循环依赖错误,因为它会在Spring容器初始化时创建代理对象,而代理对象的创建可能依赖于其他尚未初始化的bean。为了解决这个问题,需要仔细检查bean之间的依赖关系,并采取适当的措施来避免循环依赖。

补充疑问点: 在ServiceA有切面的时候,也是会给ServiceA创建代理对象的,但不会引发循环依赖。这与@Async有什么不同?

在ServiceA有切面时,Spring确实会为ServiceA创建一个代理对象。然而,这种情况下不会引发循环依赖,是因为切面逻辑通常与业务逻辑分离,不会直接影响bean之间的依赖关系。

当使用@Async注解时,Spring会为包含@Async注解的方法创建一个代理对象。这个代理对象会拦截方法调用,并将其作为异步任务提交给TaskExecutor。在这个过程中,代理对象可能会涉及到依赖注入,从而导致循环依赖问题。

然而,在使用切面(如AOP)时,代理对象主要用于在方法调用前后执行一些额外的逻辑(如日志记录、事务管理等)。这些逻辑通常与业务逻辑分离,不会直接影响bean之间的依赖关系。因此,在这种情况下,即使为ServiceA创建了代理对象,也不太可能引发循环依赖问题。

总之,@Async注解和切面在代理对象的创建和使用上有所不同。使用@Async注解时,代理对象可能会涉及到依赖注入,从而导致循环依赖问题。而在使用切面时,代理对象主要用于执行额外的逻辑,不会直接影响bean之间的依赖关系。因此,使用切面时,不太可能引发循环依赖问题。

参考资料:
https://www.bilibili.com/video/BV1YM41127H5/?spm_id_from=333.788&vd_source=4d4988a4c411aa57e0026539e4c7cccc

https://www.bilibili.com/video/BV1D14y1P7dU/?spm_id_from=333.337.search-card.all.click&vd_source=4d4988a4c411aa57e0026539e4c7cccc

文字参考:https://blog.csdn.net/zcdlove/article/details/124917536

文字说明由GPT-4提供。

相关文章

  • 2019-06-27

    Spring @Async依赖循环 解决办法: (1) 程序结构调整,避免循环依赖。 (2) 把带有@Async注...

  • 浅谈python中的循环导入

    循环导入会报错,报找不到依赖的错误,也就是报找不到模块的错误。如下类似。 这确实很头疼,明明有这个文件或模块,就是...

  • springboot异步任务

    启动类--添加@EnableAsync注解 定义异步任务--添加@Async注解 @Async注解也可以添加在方法...

  • @Aysnc

    Spring Boot @Async @Async注解包含在Web依赖中本质上就是Springboot帮你托管了线...

  • Spring线程池使用心得

    加了@Async注解的方法和调用其的方法不能再同一个类中,否则会导致异步不起作用。 启用多线程需要添加@Enabl...

  • spring 注解生效和java代理

    spring使用时,在同一个类中,一个方法调用另外一个有注解(比如@Async,@Transational)的方法...

  • spring 注解生效和java代理

    spring使用时,在同一个类中,一个方法调用另外一个有注解(比如@Async,@Transational)的方法...

  • gradle 排除排除本地项目 部分依赖

    项目依赖module时可能会有相同的依赖,就会报以下错误: gradle 排除部分依赖:以前都是以为只有 用坐标依...

  • @Async 注解

    @Async 注解 异步注解可以标注在一个类或者一个方法上面(不包含静态方法和构造方法);使用这个注释的前提条件是...

  • Spring Boot Test Mockito Mock @A

    在写SpringBoot单元测试中,需要mock一个Bean的一个方法,但是该方法有@Async注解。不管怎么写M...

网友评论

      本文标题:给一个方法加了@Async注解后,可能就会报有循环依赖的错误,这

      本文链接:https://www.haomeiwen.com/subject/qsfcwdtx.html