Ho un grafico di fagioli Spring che si autowire l'un l'altro. Pesantemente rappresentazione semplificata:Spring crea più istanze di un singleton?
<context:annotation-config/>
<bean class="Foo"/>
<bean class="Bar"/>
<bean class="Baz"/>
...
public class Foo {
@Autowired Bar bar;
@Autowired Baz baz;
}
public class Bar {
@Autowired Foo foo;
}
public class Baz {
@Autowired Foo foo;
}
Tutti questi fagioli non hanno ambito specificato che implicano sono single (Rendendole singletons espliciti non cambia nulla, ho provato).
Il problema è che, dopo l'istanza di un contesto singola applicazione, le istanze di Bar
e Baz
contengono diversi istanze di Foo
. Come è potuto accadere?
Ho provato a creare public no constrs constructor per Foo
e il debug ha confermato Foo
viene creato più di una volta. La traccia di stack per tutte queste creazioni è here.
ho anche cercato di attivare la registrazione di debug per la primavera, e tra tutte le altre linee, ha ottenuto la seguente:
DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'Foo'
DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'Foo'
DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'Foo'
ho capito che i miei fagioli sono riferimenti incrociati tra loro, ma mi si aspetterebbe framework Spring rispettare lo scope di singleton e inizializzare un bean singleton una volta e quindi autorizzarlo su chiunque lo desideri.
Il fatto interessante che se uso vecchia scuola private
costruttore con public static Foo getInstance
di accesso, questo funziona bene - senza eccezioni sono gettati durante l'installazione contesto.
FWIW, Sto usando Spring versione 3.0.5 (anche provato con 3.1.2, stessi risultati) con costruttore o.s.c.s.ClassPathXmlApplicationContext(String ...configLocations)
.
Posso facilmente convertire il mio codice per utilizzare l'inizializzatore statico ma voglio capire perché si comporterebbe in questo modo. è un insetto?
EDIT: Alcuni ulteriori indagini hanno dimostrato che
- Dopo che il contesto di applicazione è inizializzato, tutte le richieste successive
context.getBean(Foo.class)
sempre restituiscono la stessa istanza diFoo
. - Sostituire
@Autowired
con setter (circa 20 utilizzi di questo bean) risulta ancora più costruzioni di questo oggetto, ma tutte le dipendenze vengono iniettate con lo stesso riferimento.
Per quanto sopra suggerisco che si tratta di un bug di primavera relativo all'implementazione di @Autowired
. Pubblicherò i forum della community Spring e pubblicheremo di nuovo qui se riuscirò a ottenere qualcosa di utile.
Potrebbe essere ovvio, ma c'è solo 1 JVM in gioco? Dipendenze circolari? –
Sì, questa è solo una JVM. Dipendenze circolari - sì, ma credo di averlo spiegato nel mio post. – mindas
Vedo ma cosa succede se si dispone ad esempio di un'iniezione costruttore? In che modo Spring dovrebbe risolvere questo problema? –