Réponses:
car lorsque le constructeur est appelé, le bean n'est pas encore initialisé - c'est-à-dire qu'aucune dépendance n'est injectée. Dans la @PostConstruct
méthode, le bean est entièrement initialisé et vous pouvez utiliser les dépendances.
car c'est le contrat qui garantit que cette méthode ne sera invoquée qu'une seule fois dans le cycle de vie du bean. Il peut arriver (bien que peu probable) qu'un bean soit instancié plusieurs fois par le conteneur dans son fonctionnement interne, mais il garantit qu'il @PostConstruct
ne sera invoqué qu'une seule fois.
Le principal problème est que:
dans un constructeur, l'injection des dépendances n'a pas encore eu lieu *
* évidemment hors Constructor Injection
Exemple du monde réel:
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
}
}
IMPORTANT :
@PostConstruct
et @PreDestroy
ont été complètement supprimés dans Java 11 .
Pour continuer à les utiliser, vous devrez ajouter le JAR javax.annotation-api à vos dépendances.
<!-- 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.
vrai avec l'injection de setter ou de champ, mais pas vrai avec l'injection de constructeur.
Si votre classe effectue toute son initialisation dans le constructeur, elle @PostConstruct
est en effet redondante.
Cependant, si votre classe a ses dépendances injectées à l'aide de méthodes de définition, le constructeur de la classe ne peut pas initialiser complètement l'objet, et parfois une initialisation doit être effectuée après l'appel de toutes les méthodes de définition, d'où le cas d'utilisation de @PostConstruct
.
Considérez le scénario suivant:
public class Car {
@Inject
private Engine engine;
public Car() {
engine.initialize();
}
...
}
Étant donné que Car doit être instancié avant l'injection sur le terrain, le moteur du point d'injection est toujours nul pendant l'exécution du constructeur, ce qui entraîne une NullPointerException.
Ce problème peut être résolu soit par injection de dépendance JSR-330 pour l'injection de constructeur Java, soit par annotations communes JSR 250 pour l'annotation de méthode Java @PostConstruct.
@PostConstruct
JSR-250 définit un ensemble commun d'annotations qui a été inclus dans Java SE 6.
L'annotation PostConstruct est utilisée sur une méthode qui doit être exécutée après l'injection de dépendance pour effectuer toute initialisation. Cette méthode DOIT être invoquée avant la mise en service de la classe. Cette annotation DOIT être prise en charge sur toutes les classes qui prennent en charge l'injection de dépendances.
JSR-250 Chap. 2.5 javax.annotation.PostConstruct
L'annotation @PostConstruct permet de définir les méthodes à exécuter après l'instanciation de l'instance et toutes les injections.
public class Car {
@Inject
private Engine engine;
@PostConstruct
public void postConstruct() {
engine.initialize();
}
...
}
Au lieu d'effectuer l'initialisation dans le constructeur, le code est déplacé vers une méthode annotée avec @PostConstruct.
Le traitement des méthodes post-construction est une simple question de trouver toutes les méthodes annotées avec @PostConstruct et de les invoquer tour à tour.
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);
}
});
}
Le traitement des méthodes post-construction doit être effectué une fois l'instanciation et l'injection terminées.
final
. Compte tenu de ce modèle, pourquoi est@PostConstruct
-il ajouté à J2EE - ils ont sûrement vu un autre cas d'utilisation?