为什么使用@PostConstruct?
在托管 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
因为当调用构造函数时,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.你总是应该更喜欢构造函数注入,但话虽如此,如果出于任何原因你必须使用字段注入,在这种情况下,主要问题是:
示例
重要
@PostConstruct
和@ PreDestroy
已完全[在 Java 11 中删除](https://jaxenter.com/jdk-11-java-ee-modules-140674.html)。要继续使用它们,您需要添加 javax. comment-api JAR 到您的依赖项。
Maven
Gradle
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:
Example
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
Gradle
如果您的类在构造函数中执行所有初始化,那么 @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
.此外,每当涉及某种代理或远程处理时,基于构造函数的初始化将无法按预期工作。
每当 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...
实际上只有一个原因 - 因为您想要执行一项需要完全构造对象的操作,例如将“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)