为什么使用@PostConstruct?
-
25-09-2019 - |
题
在托管 Bean 中, @PostConstruct
在常规 Java 对象构造函数之后调用。
我为什么要使用 @PostConstruct
通过 bean 初始化,而不是常规构造函数本身?
解决方案
因为当调用构造函数时,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到您的依赖关系。
的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
的使用情况。
考虑以下情形:
public class Car {
@Inject
private Engine engine;
public Car() {
engine.initialize();
}
...
}
由于汽车具有前场注入到被实例化,所述注射点发动机仍空的构造方法的执行过程中,产生一个NullPointerException。
此问题可以或者通过 JSR-330 Java依赖注入解决构造器注入或用于Java @PostConstruct方法注解JSR 250个通用注解。
<强> @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();
}
...
}
而不是执行在构造函数中初始化的,代码被移动到与带注释@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);
}
});
}
的后构建体的方法的处理过程的实例化和注射已经完成之后被执行。
另外构造基于初始化不会如预期每当某种进行代理或远程处理的参与工作。
在CT将调用每当一个EJB被反序列,每当一个新的代理获取它创造...