[Java] Зачем использовать @PostConstruct?



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
    }
}

Надеюсь, это поможет.

Question

В управляемом компоненте @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);
        }
      });
}

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






Links