Attributo Spring @PostConstruct vs. init-method


103

C'è qualche differenza tra l'utilizzo @PostConstructdell'annotazione e la dichiarazione dello stesso metodo init-methoddella configurazione Spring XML?

Risposte:


153

No praticamente non penso ci sia alcuna differenza ma ci sono delle priorità nel modo in cui funzionano. @PostConstruct, init-methodsono BeanPostProcessors.

  1. @PostConstructè un'annotazione JSR-250 mentre init-methodè il modo in cui Spring ha un metodo di inizializzazione.
  2. Se si dispone di un @PostConstructmetodo, questo verrà chiamato prima prima che vengano chiamati i metodi di inizializzazione.
  3. Se il tuo bean implementa InitializingBean ed esegue l'override afterPropertiesSet, prima @PostConstructviene chiamato, poi afterPropertiesSete poi init-method.

Per maggiori informazioni puoi controllare la documentazione di riferimento di Spring .

Prima delle specifiche JSR 250, l'uso del metodo init in xml era il modo preferito, in quanto disaccoppia le classi java (bean) da qualsiasi classe / annotazione specifica della primavera, quindi se stai costruendo una libreria che non ha bisogno di dipendere dai bean dell'infrastruttura della primavera quindi è stato preferito l'uso del metodo init. Durante la creazione del metodo è possibile specificare il metodo che deve essere chiamato come metodo di inizializzazione.

Ora con l'introduzione delle specifiche JSR 250 in Java EE e il supporto Spring di queste annotazioni, la dipendenza dal framework Spring è stata ridotta in una certa misura.

Ma devo ammettere che l'aggiunta di queste cose aumenta la leggibilità del codice, quindi ci sono pro e contro entrambi gli approcci.


23
Se un bean utilizza più di uno di questi metodi e si affida all'ordine di inizializzazione, sarà orribilmente complesso e non gestibile.
Donal Fellows

2
@Donal Abbastanza vero. Stavo solo fornendo informazioni su come funziona.
Aravind A

1
V'è una differenza importante: È necessario configurare specificamente primavera per le annotazioni di processo per rendere il lavoro @PostConstruct: stackoverflow.com/q/3434377/134898
Juan Calero

@DonalFellows, ma devi saperlo se intendi sostenere gli esami di certificazione;)
S.Klechkovski

@DonalFellows - Puoi elaborare la tua risposta? Intendo le difficoltà incontrate se un bean fa affidamento sull'ordine di inizializzazione. In realtà voglio sapere qual è il migliore. PostConstruct o Bean (initMethod = "init") per eseguire alcune operazioni di inizializzazione da un bean prima che serva qualsiasi richiesta?
Ayaskant

19

Non c'è vera differenza. Dipende da come preferisci configurare il tuo sistema, ed è una questione di scelta personale. Io stesso, preferisco usare le @PostConstructannotazioni per il mio codice (poiché il bean è configurato correttamente solo dopo che il metodo è stato chiamato) e lo uso init-methodquando instanzio i bean da librerie non compatibili con Spring (non posso applicare annotazioni lì, ovviamente!) ma posso capire totalmente le persone che vogliono fare tutto in un modo o nell'altro.



3

Come puoi vedere nel diagramma sottostante di Bean Creation Life-Cycle Callback .

Richiamo del ciclo di vita della creazione di fagioli

Questo 3 passaggio si verifica nel callback del ciclo di vita della creazione di fagioli:

  1. Si dice che @PostConstructsarà chiamato.
  2. Se InitializingBeanè implementato, afterPropertiesSet()verrà chiamato.
  3. Se la definizione del bean contiene init-methodo @Bean(initmethod="..")allora chiama il metodo init.

Questo diagramma è tratto da Pro Spring 5: una guida approfondita a Spring Framework e ai suoi strumenti


3

Ci potrebbe essere differenza tra @PostConstructe init-methodperché @PostConstructviene gestita nella postProcessAfterInitializationfase di inizializzazione fagiolo ( AbstractAutowireCapableBeanFactory.initializeBean()metodo) da CommonAnnotationBeanPostProcessor, mentre initmetodo viene chiamato dopo il completamento della postProcessBeforeInitializationfase (e, per questa materia, prima dell'inizio della postProcessAfterInitializationfase).
EDIT : Quindi, la sequenza è: 1) postProcessBeforeInitializationfase, 2) initmetodo viene chiamato, 3) postProcessAfterInitializationfase, che chiama @PostConstructmetodo

(Come nota a margine, una dichiarazione dalla risposta accettata

@PostConstruct, init-method sono BeanPostProcessors

non è del tutto corretto: @PostConstructè gestito da un metodo BeanPostProcessor, initnon lo è.)

Ci sarà differenza se alcuni (potenzialmente personalizzati) BeanPostProcessor, che sono configurati con ( Ordered.getOrder()) per essere eseguiti dopo CommonAnnotationBeanPostProcessor, stanno facendo qualcosa di serio nel suo postProcessBeforeInitializationmetodo.
Non c'è alcuna differenza con la configurazione predefinita di Spring BeanPostProcessorsperché tutti quelli BeanPostProcessorsconfigurati per essere eseguiti dopo CommonAnnotationBeanPostProcessor, non fanno nulla nel postProcessBeforeInitializationmetodo.

In conclusione, la risposta accettata e simili sono giuste ... nel 99% dei casi, e questo post è solo per rendere omaggio a un concetto "il diavolo è nei dettagli"


Ciao! Ciò crea confusione, se PostConstruct viene eseguito prima del metodo init, come viene gestito da postProcessAfterInitialization se il metodo init viene eseguito dopo postProcessBeforeInitialization e prima di postProcessAfterInitialization ???
Maxrunner

@ Maxrunner, scusa per la confusione e molte grazie per averlo informato! In effetti, non ho mai inteso dire che PostConstruct viene eseguito prima del metodo init. Ad ogni modo, ho aggiornato la mia risposta con alcuni chiarimenti
igor.zh

2

Codice completo qui: https://github.com/wkaczurba/so8519187 ( spring-boot )

Utilizzo delle annotazioni:

@Slf4j
@Component
public class MyComponent implements InitializingBean {

    @Value("${mycomponent.value:Magic}")
    public String value;

    public MyComponent() {
        log.info("MyComponent in constructor: [{}]", value); // (0) displays: Null
    }

    @PostConstruct
    public void postConstruct() {
        log.info("MyComponent in postConstruct: [{}]", value); // (1) displays: Magic
    }

    @Override // init-method; overrides InitializingBean.afterPropertiesSet()
    public void afterPropertiesSet() {
        log.info("MyComponent in afterPropertiesSet: [{}]", value);  // (2) displays: Magic
    }   

    @PreDestroy
    public void preDestroy() {
        log.info("MyComponent in preDestroy: [{}]", value); // (3) displays: Magic
    }
}

Ci ottiene:

Aggiornamento di org.springframework.context in corso ...

MyComponent nel costruttore: [null]
MyComponent in postConstruct: [Magic]
MyComponent in afterPropertiesSet: [Magic]
...

Registrazione dei bean per l'esposizione JMX all'avvio
DemoApplication avviata in 0,561 secondi (JVM in esecuzione per 1.011)
Chiusura org.springframework.context .. Annullamento della registrazione dei bean esposti a JMX allo spegnimento

...
MyComponent in preDestroy: [Magic]

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.