Antworten:
Denn wenn der Konstruktor aufgerufen wird, ist die Bean noch nicht initialisiert - dh es werden keine Abhängigkeiten eingefügt. In der @PostConstruct
Methode ist die Bean 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 eine Bean in ihrer internen Arbeitsweise mehrmals vom Container instanziiert wird, dies garantiert jedoch, dass @PostConstruct
sie nur einmal aufgerufen wird.
Das Hauptproblem ist:
In einem Konstruktor ist die Injektion der Abhängigkeiten noch nicht erfolgt *
* offensichtlich ohne Konstruktorinjektion
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
wurden in Java 11 vollständig entfernt .
Um sie weiterhin verwenden zu können, müssen Sie Ihren Abhängigkeiten die JAR javax.annotation-api hinzufügen .
<!-- 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'
in a constructor, the injection of the dependencies has not yet occurred.
wahr mit Setter- oder Feldinjektion, aber nicht wahr mit Konstruktorinjektion.
Wenn Ihre Klasse die gesamte Initialisierung im Konstruktor durchführt, @PostConstruct
ist sie tatsächlich redundant.
Wenn jedoch die Abhängigkeiten Ihrer Klasse mithilfe von Setter-Methoden eingefügt wurden, 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
.
Stellen Sie sich das folgende Szenario vor:
public class Car {
@Inject
private Engine engine;
public Car() {
engine.initialize();
}
...
}
Da Car vor der Feldeinspritzung instanziiert werden muss, ist die Einspritzpunkt-Engine 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 für die Java- Konstruktorinjektion oder durch JSR 250 Common Annotations für die Annotation der Java @ PostConstruct-Methode gelöst werden.
@ PostConstruct
JSR-250 definiert einen allgemeinen Satz von Anmerkungen, die in Java SE 6 enthalten sind.
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 Anmerkung MUSS für alle Klassen unterstützt werden, die die Abhängigkeitsinjektion unterstützen.
JSR-250 Kap. 2.5 javax.annotation.PostConstruct
Mit der Annotation @PostConstruct kann die Definition von Methoden 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.
Bei der Verarbeitung von Post-Konstrukt-Methoden müssen einfach 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 der Nachkonstruktionsmethoden muss nach Abschluss der Instanziierung und Injektion durchgeführt werden.
final
. Warum wird@PostConstruct
J2EE angesichts dieses Musters hinzugefügt - sie müssen sicherlich einen anderen Anwendungsfall gesehen haben?