为什么使用@PostConstruct?

在托pipebean中,在普通的Java对象构造函数之后调用@PostConstruct

为什么我会使用@PostConstruct来初始化bean,而不是常规的构造函数本身?

  • 因为当构造函数被调用的时候,这个bean还没有被初始化 – 也就是说没有dependency injection。 在@PostConstruct方法中,bean被完全初始化,你可以使用依赖关系。

  • 因为这是保证这个方法在bean生命周期中仅被调用一次的合约。 它可能发生(虽然不太可能),一个bean被内部工作的容器多次实例化,但是它保证了@PostConstruct只会被调用一次。

如果您的类在构造函数中执行了所有初始化,那么@PostConstruct确实是多余的。

但是,如果你的类有使用setter方法注入的依赖项,那么这个类的构造函数就不能完全初始化这个对象,有时在所有的setter方法被调用之后,需要执行一些初始化操作,所以@PostConstruct的用例。

其他的答案,特别是@ Bozho的答案,已经解释了主要问题(其中包括):

在构造函数中,依赖关系的注入还没有发生

如果有人仍然怀疑这是什么意思,这是一个真实的世界的例子刚刚发生在我身上:

 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 } } 

希望有所帮助。

当涉及代理或远程处理的时候,基于构造函数的初始化也不会像预期的那样工作。

只要EJB被反序列化,每当一个新的代理被创build时,ct就会被调用。

考虑以下情况:

 public class Car { @Inject private Engine engine; public Car() { engine.initialize(); } ... } 

由于Car必须在字段注入之前实例化,注入点引擎在构造函数的执行期间仍为空,导致NullPointerException。

这个问题可以通过JSR-330dependency injection为Java构造函数注入来解决,也可以通过Java @PostConstruct方法注解的JSR 250通用注解来解决。

@PostConstruct

JSR-250定义了一组已经包含在Java SE 6中的通用注释。

PostConstruct注释用于在dependency injection完成之后需要执行的方法来执行任何初始化。 这个方法必须在类被投入使用之前调用。 所有支持dependency injection的类都必须支持该注解。

JSR-250章节 2.5 javax.annotation.PostConstruct

@PostConstruct注解允许在实例化实例化后执行方法的定义,并且执行所有的注入。

 public class Car { @Inject private Engine engine; @PostConstruct public void postConstruct() { engine.initialize(); } ... } 

代码不是在构造函数中执行初始化,而是移动到用@PostConstruct注解的方法。

后期构build方法的处理是find用@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); } }); } 

后构build方法的处理必须在实例化和注入完成之后执行。