java jframe пример - Зачем использовать @PostConstruct?





2 Answers

Основная проблема заключается в том, что:

в конструкторе инъекции зависимостей еще не произошло *

* очевидно, исключая инъекцию конструктора

Реальный пример:

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>

Gradle

// https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api
compile group: 'javax.annotation', name: 'javax.annotation-api', version: '1.3.2'
аннотация swing компоненты

В управляемом компоненте @PostConstruct вызывается после обычного конструктора объектов Java.

Почему я должен использовать @PostConstruct для инициализации bean-компонентом вместо обычного конструктора?




Рассмотрим следующий сценарий:

public class Car {
  @Inject
  private Engine engine;  

  public Car() {
    engine.initialize();  
  }
  ...
}

Поскольку автомобиль должен быть создан до ввода в эксплуатацию, двигатель точки впрыска остается нулевым во время выполнения конструктора, в результате чего возникает исключение NullPointerException.

Эта проблема может быть решена либо JSR-330 Injection Injection для встраивания конструктора Java, либо JSR 250 Common Annotations для аннотации метода Java @PostConstruct.

@PostConstruct

JSR-250 определяет общий набор аннотаций, который был включен в Java SE 6.

Аннотации PostConstruct используются для метода, который необходимо выполнить после того, как выполняется инъекция зависимостей для выполнения любой инициализации. Этот метод ДОЛЖЕН быть вызван до того, как класс будет запущен в эксплуатацию. Эта аннотация ДОЛЖНА поддерживаться на всех классах, поддерживающих инъекцию зависимостей.

JSR-250 Chap. 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);
        }
      });
}

Обработка постконструктивных методов должна выполняться после завершения инкапсуляции и впрыска.




Related