Java 为什么使用@PostConstruct?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3406555/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why use @PostConstruct?
提问by Jan
In a managed bean, @PostConstruct
is called after the regular Java object constructor.
在托管 bean 中,@PostConstruct
在常规 Java 对象构造函数之后调用。
Why would I use @PostConstruct
to initialize by bean, instead of the regular constructor itself?
为什么我要使用@PostConstruct
bean 初始化,而不是常规构造函数本身?
采纳答案by Bozho
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.
因为当构造函数被调用时,bean 尚未初始化——即没有注入依赖项。在该
@PostConstruct
方法中,bean 已完全初始化,您可以使用依赖项。因为这是保证此方法在 bean 生命周期中仅被调用一次的契约。容器在其内部工作中多次实例化 bean 的情况可能会发生(尽管不太可能),但它保证
@PostConstruct
只会被调用一次。
回答by skaffman
If your class performs all of its initialization in the constructor, then @PostConstruct
is indeed redundant.
如果您的类在构造函数中执行其所有初始化,那么@PostConstruct
确实是多余的。
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
.
但是,如果您的类使用 setter 方法注入了其依赖项,则该类的构造函数无法完全初始化对象,有时需要在调用所有 setter 方法后执行一些初始化,因此使用@PostConstruct
.
回答by struberg
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...
每当 EJB 被反序列化,以及每当为其创建新代理时,ct 都会被调用......
回答by Andrea Ligios
The mainproblem is that:
的主要问题是:
in a constructor, the injection of the dependencies has not yet occurred*
在构造函数中,依赖项的注入尚未发生*
*obviously excluding Constructor Injection
*显然不包括构造函数注入
Real-world 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.
重要提示:
@PostConstruct
并且@PreDestroy
已在 Java 11 中完全删除。
To keep using them, you'll need to add the javax.annotation-apiJAR to your dependencies.
要继续使用它们,您需要将javax.annotation-apiJAR添加到您的依赖项中。
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'
回答by Humoyun Ahmad
Consider the following scenario:
考虑以下场景:
public class Car {
@Inject
private Engine engine;
public Car() {
engine.initialize();
}
...
}
Since Car has to be instantiated prior to field injection, the injection point engine is still null during the execution of the constructor, resulting in a NullPointerException.
由于 Car 必须在字段注入之前实例化,因此在构造函数执行期间注入点引擎仍然为 null,从而导致 NullPointerException。
This problem can be solved either by JSR-330 Dependency Injection for Javaconstructor injection or JSR 250 Common Annotations for the Java @PostConstruct method annotation.
这个问题可以通过用于 Java构造函数注入的JSR-330 依赖注入或用于 Java @PostConstruct 方法注解的 JSR 250 通用注解来解决。
@PostConstruct
@PostConstruct
JSR-250 defines a common set of annotations which has been included in Java SE 6.
JSR-250 定义了 Java SE 6 中包含的一组通用注释。
The PostConstruct annotation is used on a method that needs to be executed after dependency injection is done to perform any initialization. This method MUST be invoked before the class is put into service. This annotation MUST be supported on all classes that support dependency injection.
JSR-250 Chap. 2.5 javax.annotation.PostConstruct
PostConstruct 注解用于需要在依赖注入完成后执行任何初始化的方法。必须在类投入使用之前调用此方法。所有支持依赖注入的类都必须支持这个注解。
JSR-250 章。2.5 javax.annotation.PostConstruct
The @PostConstruct annotation allows for the definition of methods to be executed after the instance has been instantiated and all injects have been performed.
@PostConstruct 注释允许在实例化实例并执行所有注入后执行方法的定义。
public class Car {
@Inject
private Engine engine;
@PostConstruct
public void postConstruct() {
engine.initialize();
}
...
}
Instead of performing the initialization in the constructor, the code is moved to a method annotated with @PostConstruct.
不是在构造函数中执行初始化,而是将代码移到用@PostConstruct 注释的方法中。
The processing of post-construct methods is a simple matter of finding all methods annotated with @PostConstruct and invoking them in turn.
后构造方法的处理很简单,就是找到所有用@PostConstruct 注释的方法并依次调用它们。
private void processPostConstruct(Class type, T targetInstance) {
Method[] declaredMethods = type.getDeclaredMethods();
Arrays.stream(declaredMethods)
.filter(method -> method.getAnnotation(PostConstruct.class) != null)
.forEach(postConstructMethod -> {
try {
postConstructMethod.setAccessible(true);
postConstructMethod.invoke(targetInstance, new Object[]{});
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
throw new RuntimeException(ex);
}
});
}
The processing of post-construct methods has to be performed after instantiation and injection have been completed.
后构造方法的处理必须在实例化和注入完成后进行。