it-swarm.com.de

Warum @PostConstruct verwenden?

In einer verwalteten Bean wird @PostConstruct wird nach dem regulären Java object Konstruktor aufgerufen.

Warum sollte ich @PostConstruct mit Bean anstelle des regulären Konstruktors selbst initialisieren?

261
Jan
  • denn wenn der Konstruktor aufgerufen wird, ist die Bean noch nicht initialisiert - d. h. es werden keine Abhängigkeiten injiziert. In dem @PostConstruct Methode Die Bean ist vollständig initialisiert und Sie können die Abhängigkeiten verwenden.

  • weil dies der Vertrag ist, der garantiert, dass diese Methode nur einmal im Bean-Lebenszyklus aufgerufen wird. Es kann vorkommen (obwohl es unwahrscheinlich ist), dass ein Bean in seiner internen Arbeitsweise vom Container mehrmals instanziiert wird, aber es garantiert, dass @PostConstruct wird nur einmal aufgerufen.

373
Bozho

Das main Problem ist, dass:

in einem Konstruktor ist die Einfügung der Abhängigkeiten noch nicht erfolgt *

* offensichtlich ohne Constructor Injection


Beispiel aus der Praxis:

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

[~ # ~] wichtig [~ # ~] : @PostConstruct und @PreDestroy wurde vollständig entfernt in Java 11.

Um sie weiterhin zu verwenden, müssen Sie die JAR-Datei javax.annotation-api zu Ihren Abhängigkeiten hinzufügen.

Maven

<!-- 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'
76
Andrea Ligios

Wenn Ihre Klasse die gesamte Initialisierung im Konstruktor durchführt, wird @PostConstruct ist in der Tat überflüssig.

Wenn die Abhängigkeiten Ihrer Klasse jedoch mithilfe von Setter-Methoden eingefügt werden, kann der Konstruktor der Klasse das Objekt nicht vollständig initialisieren, und manchmal muss eine Initialisierung durchgeführt werden, nachdem alle Setter-Methoden aufgerufen wurden, daher der Anwendungsfall von @PostConstruct.

52
skaffman

Stellen Sie sich das folgende Szenario vor:

public class Car {
  @Inject
  private Engine engine;  

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

Da Car vor der Feldinjektion instanziiert werden muss, ist die Einspritzpunktmaschine während der Ausführung des Konstruktors immer noch null, was zu einer NullPointerException führt.

Dieses Problem kann entweder durch JSR-330 Dependency Injection for Java Konstruktorinjektion oder durch JSR 250 Common Annotations for the Java @PostConstruct method annotation) gelöst werden.

@ PostConstruct

JSR-250 definiert einen allgemeinen Satz von Anmerkungen, der in Java SE 6 enthalten ist.

Die PostConstruct-Annotation wird für eine Methode verwendet, die ausgeführt werden muss, nachdem die Abhängigkeitsinjektion durchgeführt wurde, um eine Initialisierung durchzuführen. Diese Methode MUSS aufgerufen werden, bevor die Klasse in Betrieb genommen wird. Diese Annotation MUSS für alle Klassen unterstützt werden, die die Abhängigkeitsinjektion unterstützen.

JSR-250 Kap. 2.5 javax.annotation.PostConstruct

Die Annotation @PostConstruct ermöglicht die Definition von Methoden, die ausgeführt werden, nachdem die Instanz instanziiert und alle Injects ausgeführt wurden.

public class Car {
  @Inject
  private Engine engine;  

  @PostConstruct
  public void postConstruct() {
    engine.initialize();  
  }
  ...
} 

Anstatt die Initialisierung im Konstruktor durchzuführen, wird der Code in eine mit @PostConstruct kommentierte Methode verschoben.

Die Verarbeitung von Post-Konstrukt-Methoden ist eine einfache Angelegenheit, bei der alle mit @PostConstruct kommentierten Methoden gefunden und nacheinander aufgerufen werden.

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

Die Verarbeitung von Postkonstruktionsmethoden muss durchgeführt werden, nachdem die Instantiierung und Injektion abgeschlossen sind.

6
Humoyun Ahmad

Auch die konstruktorbasierte Initialisierung funktioniert nicht wie vorgesehen, wenn eine Art von Proxy oder Remoting erforderlich ist.

Das ct wird aufgerufen, wenn ein EJB deserialisiert wird und wenn ein neuer Proxy dafür erstellt wird ...

1
struberg