Jan*_*Jan 274 java dependency-injection jsr299 java-ee cdi
在托管bean中,@PostConstruct在常规Java对象构造函数之后调用.
我为什么要使用@PostConstructbean初始化,而不是常规构造函数本身?
Boz*_*zho 382
因为在调用构造函数时,bean尚未初始化 - 即没有注入依赖项.在该@PostConstruct方法中,bean已完全初始化,您可以使用依赖项.
因为这是保证在bean生命周期中只调用一次此方法的契约.可能会发生(尽管不太可能)容器在其内部工作中多次实例化bean,但它保证@PostConstruct只调用一次.
And*_*ios 78
的主要问题是:
在构造函数中,依赖项的注入尚未发生*
*显然不包括构造函数注入
现实世界的例子:
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
}
}
Run Code Online (Sandbox Code Playgroud)
重要提示:
@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>
Run Code Online (Sandbox Code Playgroud)
// https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api
compile group: 'javax.annotation', name: 'javax.annotation-api', version: '1.3.2'
Run Code Online (Sandbox Code Playgroud)
ska*_*man 58
如果您的类在构造函数中执行所有初始化,那么@PostConstruct确实是多余的.
但是,如果你的类使用setter方法注入了它的依赖项,那么类的构造函数不能完全初始化对象,有时需要在调用所有setter方法之后执行一些初始化,因此用例是@PostConstruct.
请考虑以下情形:
public class Car {
@Inject
private Engine engine;
public Car() {
engine.initialize();
}
...
}
Run Code Online (Sandbox Code Playgroud)
由于Car必须在字段注入之前进行实例化,因此注入点引擎在构造函数执行期间仍为null,从而导致NullPointerException.
这个问题可以通过Java构造函数注入的JSR-330依赖注入或Java @PostConstruct方法注释的JSR 250 Common Annotations来解决.
@PostConstruct
JSR-250定义了一组通用的注释,这些注释已包含在Java SE 6中.
PostConstruct注释用于在完成依赖项注入以执行任何初始化之后需要执行的方法.必须在类投入使用之前调用此方法.必须在支持依赖注入的所有类上支持此注释.
JSR-250 Chap.2.5 javax.annotation.PostConstruct
@PostConstruct注释允许在实例化实例并且已执行所有注入之后定义要执行的方法.
public class Car {
@Inject
private Engine engine;
@PostConstruct
public void postConstruct() {
engine.initialize();
}
...
}
Run Code Online (Sandbox Code Playgroud)
代码不是在构造函数中执行初始化,而是移动到使用@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);
}
});
}
Run Code Online (Sandbox Code Playgroud)
必须在实例化和注入完成后执行后构造方法的处理.
| 归档时间: |
|
| 查看次数: |
197698 次 |
| 最近记录: |