Spring是怎么解决Bean之间的循环依赖的?

Spring Bean的初始化是首先调用Bean的默认构造器,然后调用set方法对属性进行注入。

如果:
A包含属性B,B包含了属性A。

例子:

@Component
public class A {
    @Autowired
    private B b;

    public void aHello(){
        System.out.println("aHello!");
    }

    public void bothHello(){
        aHello();
        b.bHello();
    }
}
@Component
public class B {
    @Autowired
    private A a;

    public void bHello(){
        System.out.println("bHello!");
    }

}
public class HelloApp {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        A a = context.getBean(A.class);
        a.bothHello();
    }
}

输出:

aHello!
bHello!

A和B循环引用,程序正常运行。请问Spring是怎么解决类似的循环引用问题的?

阅读 13.2k
5 个回答

先创建基本的Bean,再依赖注入(DI)。这样就没什么问题,解释得通。
比如顺序如下:

  1. new出A的实例,

  2. new出B的实例,

  3. A Bean中的b字段赋值B的实例,

  4. B bean中的a字段赋值A的实例。

循环依赖只会在构造器中产生,spring会抛出UnsatisfiedDependencyException异常

ublic class Test {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("Test.xml");


        System.out.println(context.getBean("a"));
        System.out.println(context.getBean("b"));
    }
}

@Component
class A{
    @Autowired
    public A(B b) {
    }
}

@Component
class B{
    @Autowired
    public B(A a) {
    }
}

你遇到这种问题会怎么做?总有个先后吧。。。肯定是先把对象构造出来,在解决依赖问题啊。
你可以覆盖默认的构造器,在里面打断点,看看具体的执行顺序呀。

public class A {
    private B b;

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

    public void say(){
        System.out.println("A");
    }
}

public class B {
    private A a;

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

    public void say(){
        System.out.println("A");
    }
}

肯定有先后顺序,你可以试试在构造方法中对对象赋值。这样spring就会卡在两个对象相互引用上。

如果只是在属性中引用,spring应该会以获取类的顺序先初始化对象,然后根据对象的属性再做赋值,这样就不会出现卡在对象相互引用上了。

  • 楼上说的对:在容器启动的时候,会把bean实例都初始化好的,你可以试试这样的一种情形,你使用了@Autowired注入一个java bean,但是不配置<bean id="" class="">,你会发现容器在启动的时候会报错,所以说明了,即使是循环依赖的关系,也是:在容器启动的时候,就会初始化好java bean,。。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏