为什么使用@PostConstruct?

发布于 2024-09-12 11:07:44 字数 112 浏览 9 评论 0原文

在托管 Bean 中,@PostConstruct 在常规 Java 对象构造函数之后调用。

为什么我要使用 @PostConstruct 来通过 bean 进行初始化,而不是常规构造函数本身?

In a managed bean, @PostConstruct is called after the regular Java object constructor.

Why would I use @PostConstruct to initialize by bean, instead of the regular constructor itself?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

那支青花 2024-09-19 11:07:44
  • 因为当调用构造函数时,bean 尚未初始化 - 即没有注入依赖项。在 @PostConstruct 方法中,bean 已完全初始化,您可以使用依赖项。

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

  • because when the constructor is called, the bean is not yet initialized - i.e. no dependencies are injected. In the @PostConstruct method the bean is fully initialized and you can use the dependencies.

  • because this is the contract that guarantees that this method will be invoked only once in the bean lifecycle. It may happen (though unlikely) that a bean is instantiated multiple times by the container in its internal working, but it guarantees that @PostConstruct will be invoked only once.

甜尕妞 2024-09-19 11:07:44

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

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


示例

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. comment-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>

Gradle

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

You always should prefer constructor injection, but having that said, if for any reason you have to use field injection, in that case the main problem is that:

in a constructor, the injection of the dependencies has not yet occurred


Example

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
    }
}

Important

@PostConstruct and @PreDestroy have been completely [removed in Java 11](https://jaxenter.com/jdk-11-java-ee-modules-140674.html).

To keep using them, you'll need to add the javax.annotation-api JAR to your dependencies.

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>

Gradle

// https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api
compile group: 'javax.annotation', name: 'javax.annotation-api', version: '1.3.2'
沉睡月亮 2024-09-19 11:07:44

如果您的类在构造函数中执行所有初始化,那么 @PostConstruct 确实是多余的。

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

If your class performs all of its initialization in the constructor, then @PostConstruct is indeed redundant.

However, if your class has its dependencies injected using setter methods, then the class's constructor cannot fully initialize the object, and sometimes some initialization needs to be performed after all the setter methods have been called, hence the use case of @PostConstruct.

給妳壹絲溫柔 2024-09-19 11:07:44

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

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

Also constructor based initialisation will not work as intended whenever some kind of proxying or remoting is involved.

The ct will get called whenever an EJB gets deserialized, and whenever a new proxy gets created for it...

十年九夏 2024-09-19 11:07:44

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

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

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

There is only really one reason - because you want to take an action that requires the object to be fully constructed, like passing the "this" reference to an executor.

All the other reasons only occur if you fail to write code according to best practices (e.g. using field injections instead of constructor injection, etc).

But, since Java is free to re-order instructions in constructors, you cannot depend on any one field being fully constructed before handing off a reference to the object to an executor (i.e, the this reference should not escape until the constructor is finished)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文