Spring的核心技术(七)---循环依赖

循环依赖

如果使用构造器注入的方法,就可能会创建一个无法解析的循环依赖的场景。

例如:类A通过构造器注入需要类B的一个实例,并且类B通过构造器注入也需要一个类A的实例。如果对类A和B做了这样的相互注入的配置,那么Spring的IoC容器会在运行时检查这种循环引用,并抛出BeanCurrentlyInCreationException异常。

一种可能的解决是修改某些类的源代码,通过Setter方法而不是构造器方法来注入依赖。或者避免使用构造器注入,只是用Setter注入。换句话说,虽然不推荐使用Setter方式来注入依赖,但这样可以配置循环依赖。

跟典型的场景(没有循环依赖)不同,循环依赖的两个Bean会强制其中的一个注入到另一个优先完全自我初始化的Bean中(这是典型的鸡生蛋,然后再蛋生鸡的场景)。

通常我们会相信Spring会做正确的事情,如在容器加载时,它会检查配置的问题,如引用了不存在的Bean和循环依赖。在实际创建Bean的时候,Spring会尽可能晚的来设置属性和解决依赖问题。这就意味着即使在Spring容器正常加载之后,也会产生对象创建不了或依赖不足等异常。例如相关的Bean会抛出不存在或无效属性之类的异常。这种方式导致某些配置问题延迟暴露,所以默认情况下ApplicationContext实现提前实例化单例模式的Bean。在实际使用相关Bean之前就创建这些Bean,会支付一些时间和内存的成本,但这样会在创建ApplicationContext时就发现配置问题,而不至于发现的较晚。这种默认的行为是可以重写的,以便让单例模式的Bean在需要时才实例化,而不是提取实例化。

如果没有循环依赖存在,在一个或多个合作用的Bean被注入到一个依赖Bean中时,每个合作用的Bean要完全配置在被注入的依赖Bean之前。这就意味着,如果Bean A依赖于Bean A,那么Spring的IoC容器在调用Bean A上的Setter方法之前要完全的配置Bean B。换句话说,实例化相关的Bean的时候(不是提取实例化单例),它所依赖的设置、以及相关的生命周期方法(如配置初始化方法或初始化Bean的回调方法)都要被调用。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring框架采用依赖注入(DI)的方式来管理Bean,这种方式会解决Bean之间的循环依赖问题。在Spring容器启动时,它会先创建所有的Bean的实例,但是并不会对所有的依赖关系进行完全的填充,而是在构建Bean实例的过程中动态地解决依赖关系,从而避免了循环依赖的问题。 当需要创建一个Bean时,会经过以下步骤: 1. 创建Bean实例:当需要创建一个Bean时,Spring会将其实例化,并创建相应的BeanDefinition对象,以描述Bean的属性、依赖关系等。 2. 填充Bean属性:在Bean实例创建后,Spring会将Bean的属性值注入到Bean实例中。如果某些属性需要其他Bean的引用作为依赖,则Spring会用一个叫做代理的对象替代这些属性,这样就避免了循环依赖。 3. 调用初始化方法:在Bean实例化和属性填充后,Spring会调用Bean的初始化方法(如果有的话)。 对于循环依赖的情况,Spring会在填充属性时采用一些特殊的机制来处理。比如,当第一个Bean需要引用第二个Bean实例时,Spring会先创建一个半成品的Bean实例,然后注入到第一个Bean中。当第一个Bean创建完成后,会将其作为参数传递给第二个Bean的构造函数或者setter方法,以完成第二个Bean的创建。这样,就避免了两个Bean之间的循环依赖问题。 综上所述,Spring框架解决Bean的循环依赖问题的核心思想就是“先创建出半成品的Bean实例,然后在后续的构造器或setter方法中完成Beans之间的注入和填充”。这种方式可以解决循环依赖问题,同时也保证了Bean之间的正确依赖关系。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值