java - Spring Boot Autowired 和 Post Construct 如何工作?

标签 java spring spring-boot dependency-injection inversion-of-control

我有以下三个类(class) -

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

@Component
public class Test {
    @Autowired
    Test2 test2;

    @PostConstruct
    public void sayHi(){
        System.out.println("Hello World");
        test2.SayHello();
    }

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

@Component
public class Test2 {
    @Autowired
    Test test;

    @PostConstruct
    public void SayHello(){
        System.out.println("Test2");
        test.sayHi();
    }
}

现在这个抛出异常 -

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'test2': Invocation of init method failed; nested exception is java.lang.NullPointerException

但是,如果我按如下方式更改 Test2 类 -

    @Component
public class Test2 {
    @Autowired
    Test test;

    @PostConstruct
    public void SayHello(){
        System.out.println("Test2");
        test.printMe();
    }
}

这个有效。如果它必须失败,为什么这两种情况都没有失败? 或者如果它必须成功,为什么在这两种情况下都没有成功?

使用 Autowiring 和后构造函数进行 Spring 初始化是如何工作的?

最佳答案

Spring实例化bean并根据它们的关系为它们注入(inject)依赖。
Spring 保证声明的 bean 在调用其注释为 @PostConstruct 的方法之前将注入(inject)/设置所有依赖项。

这里是bean之间的关系:

Test --uses--> Test2

Test2 --uses--> Test

这里是如何工作的:

1) Spring 实例化一个 bean,然后实例化另一个 bean,而不注入(inject)它们的依赖项。到目前为止,顺序并不重要。
2) Spring 为第一个 bean 注入(inject)依赖项。由于此处的依赖关系是双向的,Spring 可以任意决定首先处理哪个 bean。在您的情况下,根据您的错误,Spring 首先处理 Test2
3) Spring 在设置其依赖关系后调用 Test2 bean 的 @PostConstruct 方法。
您定义的方法调用使用依赖项字段的 Test bean 的方法 (Test2 test2)。 但由于该 bean 的依赖关系尚未设置, 该字段为空,访问它会触发 NPE。

在您的工作案例中,您从 Test2 调用不引用其依赖项字段的 Test 方法。

请注意,通常不建议使用循环依赖。以下是它可能产生的问题的说明。
当您无法删除它们时,您至少应该避免在 @PostConstruct 方法中调用另一个 bean,因为它会破坏容器在初始化期间打破循环所完成的工作。

关于java - Spring Boot Autowired 和 Post Construct 如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60225433/

相关文章:

java - 将包含图表的 docx 转换为 PDF

Java Integer.ParseInt 错误

java - 滚动 logback 日志记录不起作用

java - JavaEE 和 Spring 如何相关/不相关?

java - Mongo Flux/Mono 获取对象

并行的Spring Boot多个缓存管理器

java - Struts1 ActionForm都是单例的,如果是的话,不同的请求属性是如何存储的

java - 如何格式化从 Java 输出的 HTML 页面?

spring - 慢子 SELECT GROUP BY JPQL 查询

java - PageRequest 的 native 查询参数