Зачем использовать @postconstruct?
-
25-09-2019 - |
Вопрос
В управляемом бобе @PostConstruct
вызывается после регулярного конструктора Java объекта.
Почему я использовал @PostConstruct
Инициализировать по бону, вместо самого обычного конструктора?
Решение
Потому что, когда вызывается конструктор, фасоль еще не инициализируется - то есть зависимости не вводится. в
@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. Баночка к вашим зависимостям.
Мавана
<!-- 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
действительно избыточный.
Однако, если ваш класс имеет свои зависимости, введенные с использованием методов сеттера, то конструктор класса не может полностью инициализировать объект, а иногда некоторая инициализация должна быть выполнена после того, как все методы сеттера были вызваны, отсюда. @PostConstruct
.
Рассмотрим следующий сценарий:
public class Car {
@Inject
private Engine engine;
public Car() {
engine.initialize();
}
...
}
Поскольку автомобиль должен быть создан до инъекции полей, механизм впрыска до сих пор до сих пор нулю при исполнении конструктора, что приводит к нулевойпорциональному экземпляру.
Эта проблема может быть решена либо Инъекция зависимости JSR-330 для Java Конструктор инъекции или общепринятые аннотации JSR 250 для аннотации метода Java @Postconstruct.
@Postconstruct.
JSR-250 определяет общий набор аннотаций, которые были включены в Java SE 6.
Аннотация постконструкции используется на методе, который необходимо выполнить после завершения инъекции зависимости для выполнения любой инициализации. Этот метод должен быть вызван до того, как класс введен в эксплуатацию. Эта аннотация должна поддерживаться на всех классах, которые поддерживают инъекцию зависимости.
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);
}
});
}
Обработка методов послеконструкции должна быть выполнена после создания экземпляра и инъекций.
Также инициализация на основе конструктора не будет работать, когда задействована какая-то прокси или удаление или удаление.
CT будет вызван всякий раз, когда EJB получает десериализацию, и всякий раз, когда для него создается новый прокси ...