Frage

In einer verwalteten Bohne, @PostConstruct nach dem regulären Java-Objekt-Konstruktor aufgerufen wird.

Warum soll ich verwenden @PostConstruct von Bohne zu initialisieren, anstelle des normalen Konstruktor selbst?

War es hilfreich?

Lösung

  • , weil, wenn der Konstruktor aufgerufen wird, wird die Bohne noch nicht initialisiert - das heißt keine Abhängigkeiten injiziert werden. Im @PostConstruct Verfahren wird die Bohne vollständig initialisiert und Sie können die Abhängigkeiten verwenden.

  • , denn dies ist der Vertrag, dass gewährleistet, dass diese Methode nur einmal im Lebenszyklus-Bean aufgerufen wird. Es kann vorkommen, (wenn auch unwahrscheinlich), dass eine Bohne mehrere Male durch den Behälter in seinem internen Arbeits instanziiert wird, aber es garantiert, dass @PostConstruct nur einmal aufgerufen wird.

Andere Tipps

Die main Problem ist, dass:

  

in einem Konstruktor hat die Injektion der Abhängigkeiten noch nicht aufgetreten *

* offensichtlich ohne Constructor Injection


Praxisbeispiel:

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 sind vollständig entfernt in Java 11 .

Damit sie verwenden, müssen Sie die hinzufügen javax.annotation-api JAR auf Ihre Abhängigkeiten.

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'

Wenn Ihre Klasse führt alle seine Initialisierung im Konstruktor, dann @PostConstruct ist in der Tat überflüssig.

Allerdings, wenn Ihre Klasse seine Abhängigkeiten hat Setter-Methoden injizierten verwenden, dann die Konstrukteurs-Klasse kann nicht vollständig um das Objekt zu initialisieren, und manchmal braucht einige Initialisierung, nachdem alle die Setter-Methoden durchgeführt werden, berufen worden, daher auch der Anwendungsfall von @PostConstruct.

Sie sich das folgende Szenario vor:

public class Car {
  @Inject
  private Engine engine;  

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

Da Car hat instanziiert Feld vor der Injektion wird der Impfstelle Motor ist immer noch null während der Ausführung des Konstrukteurs, was zu einer Nullpointer.

Dieses Problem kann nicht gelöst werden, indem man JSR-330 Dependency Injection for Java Konstruktor Injektion oder JSR 250 Allgemeine Anmerkungen für die Java @PostConstruct Methode Anmerkung.

@PostConstruct

JSR-250 definiert einen gemeinsamen Satz von Anmerkungen, die in Java SE 6 aufgenommen worden ist.

  

Die PostConstruct Anmerkung wird auf ein Verfahren verwendet, dass Bedürfnisse sein   nach Dependency Injection ausgeführt wird, erfolgt jede auszuführen   Initialisierung. Diese Methode muss aufgerufen werden, bevor die Klasse Put   in Betrieb genommen. Diese Anmerkung muss auf allen Klassen getragen werden, dass   Unterstützung Dependency Injection.

     

JSR-250 Kap. 2.5 javax.annotation.PostConstruct

Die @PostConstruct Anmerkung für die Definition von Methoden ermöglicht ausgeführt werden, nachdem die Instanz instanziiert wurde und alle einspritzt durchgeführt wurden.

public class Car {
  @Inject
  private Engine engine;  

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

Statt die Initialisierung im Konstruktor durchgeführt wird, wird der Code auf ein Verfahren bewegt mit @PostConstruct kommentiert.

Die Verarbeitung von Post-Konstrukt Verfahren ist eine einfache Sache, alle Methoden zu finden, mit @PostConstruct kommentiert und sich wiederum aufgerufen wird.

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 Post-Konstrukt Methoden durchgeführt werden muss nach der Instanzierung und Injektion abgeschlossen sind.

Auch Konstruktor basierte Initialisierung wird nicht funktionieren wie vorgesehen, wenn irgendeine Art von Proxying oder Remoting beteiligt ist.

Die ct wird aufgerufen, wenn ein EJB deserialisiert wird, und wann immer ein neuer Proxy wird für sie erstellt ...

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top