Відповіді:
тому що, коли викликається конструктор, боб ще не ініціалізований - тобто не вводяться залежності. У @PostConstruct
методі боб повністю ініціалізується, і ви можете використовувати залежності.
оскільки це договір, який гарантує, що цей метод буде застосований лише один раз у життєвому циклі бобів. Може статися (хоча малоймовірно), що контейнер кілька разів інстанціює контейнер у його внутрішній роботі, але це гарантує, що @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.
вірно з сетером або полевим впорскуванням, але не відповідає дійсності для конструктора.
Якщо ваш клас виконує всю свою ініціалізацію в конструкторі, то @PostConstruct
це справді зайве.
Однак, якщо у вашого класу введені залежності за допомогою методів встановлення, конструктор класу не може повністю ініціалізувати об'єкт, і іноді потрібно виконати деяку ініціалізацію після виклику всіх методів встановлення, отже, і випадку використання @PostConstruct
.
Розглянемо наступний сценарій:
public class Car {
@Inject
private Engine engine;
public Car() {
engine.initialize();
}
...
}
Оскільки автомобіль доводиться екземплярувати перед польовим впорскуванням, двигун точки вприскування все ще є нульовим під час виконання конструктора, що призводить до NullPointerException.
Цю проблему можна вирішити або за допомогою інжекцій залежності JSR-330 для введення конструктора Java або загальних анотацій JSR 250 для анотації методу Java @PostConstruct.
@PostConstruct
JSR-250 визначає загальний набір анотацій, який був включений у Java SE 6.
Анотація PostConstruct використовується для методу, який потрібно виконати після введення залежності для виконання будь-якої ініціалізації. Цей метод ОБОВ'ЯЗКОВО використовувати, перш ніж клас буде введений в експлуатацію. Цю примітку ОБОВ'ЯЗКОВО підтримувати для всіх класів, які підтримують введення залежності.
JSR-250 гл. 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 - вони, напевно, вже бачили інший випадок використання?