Come chiamare un metodo al termine dell'inizializzazione del bean?


237

Ho un caso d'uso in cui devo chiamare un metodo (non statico) nel bean solo una volta al caricamento di ApplicationContext. Va bene, se uso MethodInvokingFactoryBean per questo? O abbiamo una soluzione migliore?

Come nota a margine, uso ConfigContextLoaderListener per caricare il contesto dell'applicazione nell'applicazione web. E voglio che se il bean 'A' viene istanziato, chiama il metodo A () una volta.

Come può essere fatto bene?

Risposte:


196

Puoi usare qualcosa come:

<beans>
    <bean id="myBean" class="..." init-method="init"/>
</beans>

Questo chiamerà il metodo "init" quando il bean viene istanziato.


15
postConstruct dovrebbe essere migliore nella maggior parte dei casi, poiché non vogliamo fare confusione con l'inizializzazione del bean di primavera.
lwpro2

4
@ lwpro2 Cosa intendi con "non voglio fare confusione con l'inizializzazione dei bean di primavera" qui?
Yngve Sneen Lindal,

@Mercer Traieste cosa devo dare per l'attributo class qui? Posso dare la classe controller qui?
KJEjava48

314

Per espandere il suggerimento di @PostConstruct in altre risposte, questa è davvero la soluzione migliore, secondo me.

  • Mantiene il codice disaccoppiato dall'API Spring (@PostConstruct è in javax. *)
  • Annota esplicitamente il metodo init come qualcosa che deve essere chiamato per inizializzare il bean
  • Non è necessario ricordare di aggiungere l'attributo init-method alla definizione del bean spring, spring chiamerà automaticamente il metodo (supponendo che si registri l'opzione annotation-config da qualche altra parte nel contesto, comunque).

9
Grazie, funziona. Nota se si desidera utilizzare con Spring è necessario includere "<context: annotation-config />" per registrare il bean CommonAnnotationBeanPostProcessor (come menzionato sopra)
khylo

2
Un adatto <context:component-scan>funziona anche e può essere utile per ridurre i tempi di avvio se nel tuo percorso di classe sono presenti librerie non Spring di grandi dimensioni.
Donal Fellows

5
JavaDoc per PostConstruct afferma che è possibile annotare un solo metodo per classe: docs.oracle.com/javaee/5/api/javax/annotation/…
Andrew Swan,

@PostConstruct non funziona con un gestore delle transazioni, consultare: forum.spring.io/forum/spring-projects/data/…
mmm

2
Anche @PostConstruct non ti sarà di grande utilità quando il bean che stai istanziando non è una classe tua ma una classe di terze parti
John Rix,

102

Esistono tre diversi approcci da considerare, come descritto nel riferimento

Usa l'attributo init-method

Professionisti:

  • Non richiede bean per implementare un'interfaccia.

Contro:

  • Nessuna indicazione immediata è richiesto questo metodo dopo la costruzione per garantire che il bean sia configurato correttamente.

Implementare InitializingBean

Professionisti:

  • Non è necessario specificare il metodo init o attivare la scansione / elaborazione delle annotazioni dei componenti.
  • Adatto per i bean forniti con una libreria, in cui non vogliamo che l'applicazione che utilizza questa libreria si occupi del ciclo di vita dei bean.

Contro:

  • Più invasivo dell'approccio con metodo init.

Utilizzare l' annotazione JSR-250 @PostConstruct per lo stile di vita

Professionisti:

  • Utile quando si utilizza la scansione dei componenti per rilevare automaticamente i bean.
  • Illustra che un metodo specifico deve essere utilizzato per l'inizializzazione. L'intento è più vicino al codice.

Contro:

  • Inizializzazione non più specificata a livello centrale nella configurazione.
  • È necessario ricordare di attivare l'elaborazione delle annotazioni (che a volte può essere dimenticata)

4
Penso che in realtà sia una buona cosa da usare @PostConstructproprio perché fa parte della classe che ha bisogno del metodo che chiama alla fine dell'elaborazione dell'inizializzazione.
Donal Fellows

Se quella classe ha davvero bisogno e non puoi farlo nel costruttore, allora lo considero un odore di codice.
user482745

39

Hai provato a implementare InitializingBean? Sembra esattamente quello che stai cercando.

Il rovescio della medaglia è che il tuo bean diventa sensibile alla primavera, ma nella maggior parte delle applicazioni non è poi così male.


2
C'è un motivo per cui sceglieresti di implementare l'interfaccia piuttosto che specificare un metodo init nell'XML?
Segna il

4
Questa è una questione di gusti. L'interfaccia fa parte del modello di componente Spring e serve solo a quello scopo, mentre per un metodo personalizzato potrebbe non essere ovvio che debba essere chiamato per completare il ciclo di vita dei componenti. Quindi questo serve principalmente alla comunicazione. Naturalmente con l'inconveniente della dipendenza introdotta dal framework Spring. Un bel modo in mezzo è l'uso di @PostConstruct, in quanto ha una semantica chiara ma non introduce la dipendenza ...
Oliver Drotbohm

7
Oliver mi dà delle belle scuse, ma in realtà mi ero appena dimenticato del metodo init :) Un'altra ragione è che il tipo stesso sa che deve essere "finito" dopo che tutte le proprietà sono state impostate - non lo è fondamentalmente qualcosa che dovrebbe essere nella configurazione.
Jon Skeet,

8

È possibile distribuire un processore BeanPost personalizzato nel contesto dell'applicazione per farlo. Oppure, se non ti dispiace implementare un'interfaccia Spring nel tuo bean, puoi usare l' interfaccia InitializingBean o la direttiva "metodo-init" (stesso link).


Qualcuno ha i dettagli su come scrivere un BeanPostProcessor. Sembra esattamente quello di cui ho bisogno. Saluti :)
Peakit

Spring spedisce con molti esempi. Basta guardare l'API JavaDoc per BeanPostProcessor e troverai collegamenti a molte classi di implementazione. Quindi guarda il codice sorgente per loro.
Rob H,

-7

Per chiarire ulteriormente qualsiasi confusione riguardo ai due approcci, ovvero l'uso di

  1. @PostConstruct e
  2. init-method="init"

Per esperienza personale, mi sono reso conto che l'utilizzo di (1) funziona solo in un contenitore servlet, mentre (2) funziona in qualsiasi ambiente, anche nelle applicazioni desktop. Pertanto, se si utilizza Spring in un'applicazione autonoma, è necessario utilizzare (2) per eseguire tale "chiamata di questo metodo dopo l'inizializzazione.


4
Tecnicamente, @PostConstruct(se utilizzato in un'app basata su Spring) è legato alla durata della vita del contesto Spring proprietario. Tali contesti possono essere utilizzati in tutti i tipi di applicazioni.
Donal Fellows

Quello era il comportamento che mi aspettavo, ma non ha funzionato per me.
Ayorinde,
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.