2009-01-08 21 views
19

Desidero dichiarare due bean e istanziarli utilizzando l'iniezione di dipendenza Spring?Come collegare i fagioli interdipendenti in primavera?

<bean id="sessionFactory" class="SessionFactoryImpl"> 
<property name="entityInterceptor" ref="entityInterceptor"/> 
</bean> 

<bean id="entityInterceptor" class="EntityInterceptorImpl"> 
<property name="sessionFactory" ref="sessionFactory"/> 
</bean> 

ma la primavera genera un'eccezione dicendo "FactoryBean che è attualmente nella creazione restituito nulla da getObject"

Perché il cablaggio di fagioli interdipendente non funziona qui? Devo specificare la proprietà defferred binding ovunque?

risposta

13

Sfortunatamente il modo in cui l'inizializzazione del contenitore funziona in Spring, un bean può essere iniettato in un altro bean solo quando è completamente inizializzato. Nel tuo caso hai una dipendenza circolare che impedisce l'inizializzazione di entrambi i bean perché dipendono l'uno dall'altro. Per aggirare questo problema è possibile implementare BeanFactoryAware in uno dei bean e ottenere il riferimento all'altro bean utilizzando beanFactory.getBean ("beanName").

+0

Non ho questo problema quando ho provato con classi semplici come BeanA e BeanB. – Sathish

+0

I secondo Sathish. Puoi farlo con 'BeanA' e' BeanB', quindi è qualcosa di più speciale in questo esempio. –

+1

Ancora meglio, non hardcode '" beanName "', ma, invece, usa il tag '' di Spring in modo che la factory inietti il ​​nome-bean in una proprietà 'String'. – Darien

3

neesh è giusto, Spring non lo fa fuori dalla scatola.

I fagioli interdipendenti indicano un problema di progettazione. Il modo "pulito" per fare ciò è ridisegnare i propri servizi in modo tale che non ci siano tali disparità, naturalmente a condizione di avere il controllo sulle implementazioni.

+0

+1 per la riprogettazione: non è necessario disporre di tale interdipendenza. –

+1

Non penso che il suo design sia in discussione qui (non sappiamo nulla del problema e della soluzione); La domanda qui è come si può affrontare le dipendenze circolari tra gli oggetti gestiti dal contenitore Spring. – neesh

+0

E la risposta, IMHO, non lo è, a meno che tu non abbia una scelta perché l'implementazione non è tua, nel qual caso le soluzioni fornite qui faranno il trucco. I due servizi sono solo un servizio, oppure esiste un terzo servizio di livello superiore in attesa di essere scoperto. – Henning

0

è possibile estendere l'ApplicactionContext che utilizzano e sovrascrivere il metodo createBeanFactory()

protected DefaultListableBeanFactory createBeanFactory(){ 
    DefaultListableBeanFactory beanFactory = super.createBeanFactory(); 
    // By default this is false; 
    beanFactory.setAllowRawInjectionDespiteWrapping(true); 
    return beanFactory; 
} 

Questo funziona, ma attenzione perché ciò consente riferimenti circolari.