Вопрос

В управляемом бобе @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 получает десериализацию, и всякий раз, когда для него создается новый прокси ...

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top