Answers:
因为在调用构造函数时,bean尚未初始化-即没有注入依赖项。在该@PostConstruct
方法中,bean已完全初始化,您可以使用依赖项。
因为这是保证在bean生命周期中仅调用一次此方法的协定。可能会发生(尽管不太可能)容器在其内部工作中多次实例化bean,但它保证@PostConstruct
仅将其调用一次。
的主要问题是:
在构造函数中,依赖项的注入尚未发生*
*显然不包括构造函数注入
实际示例:
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中完全删除。
为了继续使用它们,您需要将javax.annotation-api JAR 添加到您的依赖项中。
<!-- 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'
in a constructor, the injection of the dependencies has not yet occurred.
对于setter或field注入为true,但对于构造函数注入为true。
如果您的类在构造函数中执行了所有初始化操作,则@PostConstruct
确实是多余的。
但是,如果您的类使用setter方法注入了其依赖项,则该类的构造函数无法完全初始化该对象,有时,在调用了所有setter方法之后,需要执行一些初始化,因此是的用例@PostConstruct
。
请考虑以下情形:
public class Car {
@Inject
private Engine engine;
public Car() {
engine.initialize();
}
...
}
由于必须在字段注入之前实例化Car,因此在构造函数执行期间注入点引擎仍为null,从而导致NullPointerException。
此问题可以通过Java构造函数注入的JSR-330依赖项注入或Java @PostConstruct方法注释的JSR 250通用注释来解决。
@PostConstruct
JSR-250定义了一组通用注释,这些注释已包含在Java SE 6中。
PostConstruct批注用于需要依赖注入完成以执行任何初始化之后需要执行的方法上。必须在类投入使用之前调用此方法。所有支持依赖注入的类都必须支持该注释。
JSR-250第1章。2.5 javax.annotation.PostConstruct
@PostConstruct批注允许实例化实例并执行所有注入后定义要执行的方法。
public class Car {
@Inject
private Engine engine;
@PostConstruct
public void postConstruct() {
engine.initialize();
}
...
}
无需在构造函数中执行初始化,而是将代码移动到以@PostConstruct注释的方法。
处理后构造方法很简单,只需查找所有用@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);
}
});
}
构造和注入完成后,必须执行构造后方法的处理。
final
。在这种模式下,为什么@PostConstruct
要添加到J2EE中-他们一定一定已经看到了另一个用例?