Perché usare @PostConstruct?

In un bean gestito, @PostConstruct viene chiamato dopo il normale costruttore di oggetti Java.

Perché dovrei usare @PostConstruct per inizializzare da bean, invece del normale costruttore stesso?

  • perché quando viene chiamato il costruttore, il bean non è ancora inizializzato, cioè non vengono iniettate dipendenze. Nel metodo @PostConstruct il bean è completamente inizializzato ed è ansible utilizzare le dipendenze.

  • perché questo è il contratto che garantisce che questo metodo sarà invocato una sola volta nel ciclo di vita del bean. Può accadere (anche se improbabile) che un bean venga istanziato più volte dal contenitore nel suo funzionamento interno, ma garantisce che @PostConstruct venga richiamato una sola volta.

Le altre risposte, in particolare quella di @ Bozho, hanno già spiegato il problema principale (tra gli altri):

in un costruttore, l’iniezione delle dipendenze non si è ancora verificata .

Nel caso qualcuno abbia ancora dei dubbi su cosa significhi, questo è un esempio del mondo reale mi è appena successo:

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

Spero possa aiutare.

Se la tua class esegue tutta la sua inizializzazione nel costruttore, allora @PostConstruct è effettivamente ridondante.

Tuttavia, se la class ha le sue dipendenze iniettate usando i metodi setter, allora il costruttore della class non può inizializzare completamente l’object, e talvolta è necessario eseguire alcune inizializzazioni dopo che tutti i metodi setter sono stati chiamati, da qui il caso d’uso di @PostConstruct .

Si consideri il seguente scenario:

 public class Car { @Inject private Engine engine; public Car() { engine.initialize(); } ... } 

Poiché Car deve essere istanziato prima dell’iniezione del campo, il motore del punto di iniezione è ancora nullo durante l’esecuzione del costruttore, risultante in una NullPointerException.

Questo problema può essere risolto da JSR-330 Dependency Injection per l’ iniezione del costruttore Java o da JSR 250 Common Annotations per l’annotazione del metodo Java @PostConstruct.

@PostConstruct

JSR-250 definisce un insieme comune di annotazioni che è stato incluso in Java SE 6.

L’annotazione PostConstruct viene utilizzata su un metodo che deve essere eseguito dopo l’esecuzione della dipendenza per eseguire qualsiasi inizializzazione. Questo metodo DEVE essere invocato prima che la class sia messa in servizio. Questa annotazione DEVE essere supportata su tutte le classi che supportano l’iniezione di dipendenza.

Cap. JSR-250 2.5 javax.annotation.PostConstruct

L’annotazione @PostConstruct consente di definire i metodi da eseguire dopo che l’istanza è stata istanziata e tutte le iniezioni sono state eseguite.

 public class Car { @Inject private Engine engine; @PostConstruct public void postConstruct() { engine.initialize(); } ... } 

Invece di eseguire l’inizializzazione nel costruttore, il codice viene spostato su un metodo annotato con @PostConstruct.

L’elaborazione dei metodi di post-costruzione è una semplice questione di trovare tutti i metodi annotati con @PostConstruct e invocarli a turno.

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

L’elaborazione dei metodi di post-costruzione deve essere eseguita dopo l’istanziazione e l’iniezione sono state completate.

Anche l’inizializzazione basata sul costruttore non funzionerà come previsto ogni volta che viene coinvolta una sorta di proxy o di remoting.

Il ct verrà chiamato ogni volta che un EJB viene deserializzato e ogni volta che viene creato un nuovo proxy per esso …