如何解决spring中循环依赖的问题

在Java开发中,循环依赖是一个常见的问题,特别是在IoC容器中。Spring框架是Java开发中广泛使用的一款框架,它通过IoC容器来管理对象的生命周期和依赖关系。然而,当两个或多个对象之间存在循环依赖时,传统的解决方式可能会导致问题。本文将介绍Spring是如何解决这个问题的。

首先,让我们了解一下循环依赖的概念。循环依赖指的是两个或多个对象相互依赖,形成一个闭环。例如,对象A依赖于对象B,而对象B又依赖于对象A。这种情况在程序运行时会导致问题,因为对象A和对象B都无法完成初始化。

为了解决这个问题,Spring引入了三种解决循环依赖的方式:构造器注入、属性注入和setter注入。下面我们分别来看这三种方式是如何解决问题的。

在这里插入图片描述

1. 构造器注入

构造器注入是Spring推荐的一种解决循环依赖的方式。当使用构造器注入时,Spring会在创建Bean时通过构造函数传入依赖的对象。这种方式可以避免循环依赖的问题,因为它是通过构造函数来传递依赖关系的,而不是通过属性或setter方法。

下面是一个使用构造器注入的例子:

public class A {
    private B b;

    public A(B b) {
        this.b = b;
    }
}

public class B {
    private A a;

    public B(A a) {
        this.a = a;
    }
}

在这个例子中,A依赖于B,B依赖于A。通过构造器注入,Spring可以在创建Bean时将A和B一起创建,从而避免了循环依赖的问题。

2. 属性注入和setter注入

虽然构造器注入可以解决循环依赖的问题,但在某些情况下,我们可能需要使用属性注入或setter注入。在这种情况下,Spring会使用一个称为“提前暴露对象”的策略来解决循环依赖。这种策略的基本思想是:在Bean实例化之前,Spring会预先创建一个代理对象,并将需要注入的属性值设置为空或默认值。当Bean实例化完成后,Spring会将代理对象替换为真正的Bean实例,从而实现属性注入或setter注入。

下面是一个例子:

public class A {
    private B b;

    public void setB(B b) {
        this.b = b;
    }
}

public class B {
    private A a;

    public void setA(A a) {
        this.a = a;
    }
}

在这个例子中,A依赖于B,B依赖于A。通过提前暴露对象的策略,Spring可以在创建Bean之前预先创建一个代理对象,并设置需要注入的属性值为空或默认值。当Bean创建完成后,Spring会将代理对象替换为真正的Bean实例,从而实现属性注入或setter注入。

3. @Lazy懒加载注解

注意:使用@Lazy的前提是要操作的Bean要使用默认的单例模式。

使用@Lazy懒加载注解可以减少springIOC容器启动过程的加载时间

@Lazy 懒加载注解使用示例

package com.spring.config;
import com.spring.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Configuration
//@Lazy注解作用于类上时,通常与@Component及其衍生Spring注解配合使用。
/*@Component
 *@Lazy
*/
public class TestLazyConfig { 
// @Lazy注解属性 Value 取值为 true、false 。默认为true 表示启用懒加载。 
//false 表示不启用,基本用不到,如果不启用的话,不需要加@Lazy注解
// @Lazy注解作用于在类方法上时,通常与@Bean注解配合使用。    
  @Lazy
  @Bean 
  public Person person() {       
    System.out.println("测试容器添加Person对象");        
    return new Person("小孙", 28, "西安");  
  }
}
新建测试类
package com.spring.test;
import com.spring.config.TestLazyConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestLazy {   
  public static void main(String[] args) {
    // @Lazy 注解启用的时候 不进行类初始化
    // 不启用的时候会进行类初始化 
    //控制台输出: 测试容器添加Person对象
    AnnotationConfigApplicationContext annotationContext = new AnnotationConfigApplicationContext(TestLazyConfig.class);
    // 第一次获取Bean对象 会进行类初始化  
    //控制台输出: 测试容器添加Person对象        
    Object person1 = annotationContext.getBean("person");        
    // 第二次获取Bean对应 不会载进行类初始化        
    Object person2 = annotationContext.getBean("person");   
  }
}
  • 7
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值