美文网首页
给一个方法加了@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提供。

    相关文章

      网友评论

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

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