Question

Dans un bean géré, @PostConstruct est appelé après le constructeur de l'objet Java régulier.

Pourquoi devrais-je utiliser pour initialiser @PostConstruct par le haricot, au lieu du constructeur régulier lui-même?

Était-ce utile?

La solution

  • parce que quand le constructeur est appelé, le haricot n'a pas encore été initialisé - à savoir pas de dépendances sont injectés. Dans la méthode @PostConstruct la fève est complètement initialisé et vous pouvez utiliser les dépendances.

  • parce que c'est le contrat qui garantit que cette méthode sera invoquée qu'une seule fois dans le cycle de vie de haricots. Il peut arriver (bien que peu probable) qu'un haricot est instancié plusieurs fois par le conteneur dans son travail interne, mais il garantit que @PostConstruct sera invoqué qu'une seule fois.

Autres conseils

principale Le problème est que:

  

dans un constructeur, l'injection des dépendances n'a pas encore eu lieu *

* sauf évidemment injection Constructor


exemple 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 en Java 11 .

Pour continuer à les utiliser, vous devrez ajouter le javax.annotation-api JAR vos dépendances.

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'

Si votre classe effectue toutes son initialisation dans le constructeur, alors @PostConstruct est en effet redondant.

Cependant, si votre classe a ses dépendances injecté à l'aide des méthodes de réglage, puis le constructeur de la classe ne peut pas initialiser complètement l'objet, et parfois une initialisation doit être effectuée après que toutes les méthodes de réglage ont été appelés, d'où l'utilisation cas de @PostConstruct.

Considérez le scénario suivant:

public class Car {
  @Inject
  private Engine engine;  

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

Comme véhicule doit être instancié avant l'injection de champ, le moteur de point d'injection est encore nulle au cours de l'exécution du constructeur, ce qui entraîne une NullPointerException.

Ce problème peut être résolu soit par JSR-330 injection de dépendances pour Java l'injection de constructeur ou JSR 250 Annotations communes pour l'annotation 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é sur une méthode qui doit être   exécutée après l'injection de dépendance est effectuée pour effectuer toute   l'initialisation. Cette méthode doit être invoquée devant la classe est mis   en service. Cette annotation DOIT être pris en charge sur toutes les classes   supporter l'injection de dépendance.

     

JSR-250 Chap. 2,5 javax.annotation.PostConstruct

L'annotation @PostConstruct permet de définir des méthodes à exécuter après l'instance a été instancié et tous injectent ont été réalisées.

public class Car {
  @Inject
  private Engine engine;  

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

Au lieu d'effectuer l'initialisation du 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 les invoquer à son 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-Construct doit être effectuée après l'instanciation et l'injection ont été achevées.

Initialisation également en fonction du constructeur ne fonctionnera pas comme prévu chaque fois une sorte de mandatement ou Remoting est impliqué.

Le ct sera appelé à chaque fois qu'un EJB se désérialisée, et chaque fois qu'un nouveau proxy est créé pour elle ...

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top