在托管 bean 中,
@PostConstruct
在常规 Java 对象构造函数之后调用。
为什么我要使用
@PostConstruct
来通过 bean 进行初始化,而不是常规构造函数本身?
因为当调用构造函数时,bean 尚未初始化 - 即没有注入依赖项。在
@PostConstruct
方法中,bean 已完全初始化,您可以使用依赖项。因为这是保证该方法在bean生命周期中仅被调用一次的契约。一个 bean 可能会在其内部工作中被容器实例化多次(虽然不太可能),但它保证
@PostConstruct
只会被调用一次。你总是应该更喜欢构造函数注入,但话虽如此,如果出于任何原因你必须使用字段注入,在这种情况下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'
如果您的类在构造函数中执行所有初始化,那么
@PostConstruct
确实是多余的。
但是,如果您的类使用 setter 方法注入依赖项,则该类的构造函数无法完全初始化对象,有时需要在调用所有 setter 方法后执行一些初始化,因此是
@PostConstruct
的用例。
此外,每当涉及某种代理或远程处理时,基于构造函数的初始化将无法按预期工作。
每当 EJB 反序列化以及为其创建新代理时,都会调用 ct...
实际上只有一个原因 - 因为您想要执行一项需要完全构造对象的操作,例如将“this”引用传递给执行器。
所有其他原因只有在您未能根据最佳实践编写代码时才会发生(例如使用字段注入而不是构造函数注入等)。
但是,由于 Java 可以自由地重新排序构造函数中的指令,因此在将对对象的引用移交给执行程序之前,您不能依赖于完全构造的任何一个字段(即,在构造函数完成之前, this 引用不应转义) )