Spring自动装配顺序和@PostConstruct

37

我对Spring中自动装配顺序和@PostConstruct逻辑有疑问。例如,以下是我的一个主要Spring Boot类的演示代码:

@SpringBootApplication
public class Demo1Application {

    @Autowired
    BeanB beanb;

    public static void main(String[] args) {
        SpringApplication.run(Demo1Application.class, args);
    }
}

还有2个 @Service 定义:

@Service
public class BeanB {

    @Autowired
    private BeanA beana ;

    @PostConstruct
    public void init(){
        System.out.println("beanb is called");
    }

    public void printMe(){
        System.out.println("print me is called in Bean B");
    }
}

@Service
public class BeanA {

    @Autowired
    private BeanB b;

    @PostConstruct
    public void init(){
        System.out.println("bean a is called");
        b.printMe();
    }
}

我得到了以下输出:

调用了bean a

在Bean B中调用了print me方法

调用了beanb


我的问题是自动装配是如何像上面的场景一步步发生的?
以及为什么可以在没有先调用其@PostConstruct方法的情况下调用beanbprintMe()方法?

3个回答

26
以下应该是可能的顺序:
  1. beanb 开始自动装配
  2. 在初始化 Beanb 类时,开始自动装配 beana
  3. 一旦创建了 beana,就会调用 @PostConstructinit() 方法
  4. init() 中,调用 System.out.println("bean a is called");
  5. 然后调用 b.printMe();,导致执行 System.out.println("print me is called in Bean B");
  6. beana 完成 @PostConstructinit() 后,会调用 beanb@PostConstructinit() 方法
  7. 然后调用 System.out.println("beanb is called");
理想情况下,可以通过 Eclipse 中的调试器更好地观察相同的过程。

Spring参考手册解释了如何解决循环依赖。首先实例化bean,然后相互注入。


1
请点击此链接以查看有关循环依赖解决方案的Spring文档:https://docs.spring.io/spring/docs/4.1.x/spring-framework-reference/html/beans.html#beans-dependency-resolution - YetAnotherBot
小心使用PostConstruct,它可能会“调用”到循环依赖项,它们仍然可能为空:https://dev59.com/E4nca4cB1Zd3GeqP5xNz#64649202 - rogerdpack

6

您在问题中展示的答案是正确的。

现在,让我们理解一下@Autowired的概念。所有@Autowired对象都在类加载后立即初始化并加载到内存中。

现在,这里是您的SpringBootApplication

@SpringBootApplication
public class Demo1Application {
    @Autowired
    BeanB beanb;   // You are trying to autowire a Bean class Named BeanB.

在你编写的上述控制台应用程序中,尝试自动装配和注入BeanB类型的对象。

现在,这是您对BeanB的定义:

@Service
public class BeanB {

    @Autowired
    private BeanA beana ;

BeanB 类中,您试图注入一个对象,这个对象是类 BeanA 的实例,而这个类也在您的控制台项目中定义。

因此,在您的 Demo1Application 中,要想注入一个类 BeanB 的对象,必须先注入一个类 BeanA 的对象。现在已经创建了类 BeanA 的对象。

如果您查看类 BeanA 的定义,可以发现:

 @Service
public class BeanA {

    @Autowired
    private BeanB b;

    @PostConstruct   // after Creating bean init() will be execute.
    public void init(){
        System.out.println("bean a is called");
        b.printMe();
    }
}

所以,在注入对象 BeanA 后,使用 @PostContruct 注解绑定的方法将开始执行。

因此,执行流程如下:

System.out.println("bean a is called");
System.out.println("print me is called in Bean B");
System.out.println("beanb is called");

0

当类A依赖于类B,而类B又依赖于类A时,会显示类未找到异常。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接