为什么使用@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方法的处理必须在实例化和注入完成之后执行。
- 如何使用dependency injection的属性?
- Ninject:使用Ninject注册一个已经创build的实例?
- 以使用知识库的工作模式为单位进行dependency injection
- 如何注入依赖到一个自我实例化的对象在spring?
- 什么是Ninject,什么时候使用它?
- 如何在ASP.NET Web窗体中使用dependency injection
- 将dependency injection到ASP.NET MVC 3操作filter中。 这种方法有什么问题?
- 有没有解决ASP.NET MVC的ContactsManager教程中的dependency injection循环问题的好方法?
- 为什么不使用IoC容器来parsing实体/业务对象的依赖关系?