为什么使用@PostConstruct?

问题描述 投票:0回答:5

在托管 bean 中,

@PostConstruct
在常规 Java 对象构造函数之后调用。

为什么我要使用

@PostConstruct
来通过 bean 进行初始化,而不是常规构造函数本身?

java dependency-injection jakarta-ee cdi jsr299
5个回答
567
投票
  • 因为当调用构造函数时,bean 尚未初始化 - 即没有注入依赖项。在

    @PostConstruct
    方法中,bean 已完全初始化,您可以使用依赖项。

  • 因为这是保证该方法在bean生命周期中仅被调用一次的契约。一个 bean 可能会在其内部工作中被容器实例化多次(虽然不太可能),但它保证

    @PostConstruct
    只会被调用一次。


146
投票

你总是应该更喜欢构造函数注入,但话虽如此,如果出于任何原因你必须使用字段注入,在这种情况下main问题是:

在构造函数中,依赖项的注入尚未发生


示例

public class Foo {

    @Inject
    Logger LOG;
        
    @PostConstruct
    public void fooInit(){
        LOG.info("This will be printed; LOG has already been injected");
    }

    public Foo() {
        LOG.info("This will NOT be printed, LOG is still null");
        // NullPointerException will be thrown here
    }
}

重要

@PostConstruct
@PreDestroy
已完全[在 Java 11 中删除](https://jaxenter.com/jdk-11-java-ee-modules-140674.html)。

要继续使用它们,您需要将 javax.annotation-api JAR 添加到您的依赖项中。

Maven

<!-- https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api -->
<dependency>
    <groupId>javax.annotation</groupId>
    <artifactId>javax.annotation-api</artifactId>
    <version>1.3.2</version>
</dependency>

摇篮

// https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api
compile group: 'javax.annotation', name: 'javax.annotation-api', version: '1.3.2'

79
投票

如果您的类在构造函数中执行所有初始化,那么

@PostConstruct
确实是多余的。

但是,如果您的类使用 setter 方法注入依赖项,则该类的构造函数无法完全初始化对象,有时需要在调用所有 setter 方法后执行一些初始化,因此是

@PostConstruct
的用例。


1
投票

此外,每当涉及某种代理或远程处理时,基于构造函数的初始化将无法按预期工作。

每当 EJB 反序列化以及为其创建新代理时,都会调用 ct...


0
投票

实际上只有一个原因 - 因为您想要执行一项需要完全构造对象的操作,例如将“this”引用传递给执行器。

所有其他原因只有在您未能根据最佳实践编写代码时才会发生(例如使用字段注入而不是构造函数注入等)。

但是,由于 Java 可以自由地重新排序构造函数中的指令,因此在将对对象的引用移交给执行程序之前,您不能依赖于完全构造的任何一个字段(即,在构造函数完成之前, this 引用不应转义) )

© www.soinside.com 2019 - 2024. All rights reserved.