Mam wykres fasoli wiosennej, który się nawzajem się nawzajem. Mocno uproszczony rysunek:Wiosna tworząc wiele wystąpień singletona?
<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;
}
wszystkich tych ziaren nie mają zakres określony które implikują one singletons (czyniąc je wyraźnymi singletons niczego nie zmienia, próbowałem).
Problemem jest to, że po chwili tworzenia kontekstu pojedynczej aplikacji instancje Bar
i Baz
zawierać różne wystąpienia Foo
. Jak to mogło się stać?
Próbowałem utworzyć publiczny konstruktor bez args dla Foo
, a debugowanie potwierdziło, że Foo
jest tworzony więcej niż jeden raz. Ślad stosu dla wszystkich tych kreacji to here.
Próbowałem również włączyć rejestrowanie debugowania na wiosnę, a wśród wszystkich innych linii, mam następujące:
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'
Rozumiem, że moje ziarna są odsyłaczy siebie, ale spodziewałbym Spring Framework aby uszanować zasięg singletonu i zainicjować pojedynczą fasolę raz, a następnie powierzyć ją każdemu, kto chce.
Ciekawostką jest fakt, że jeśli korzystam ze starego szkolnego konstruktora private
z akcesorium public static Foo getInstance
, działa to dobrze - żadne wyjątki nie są generowane podczas konfiguracji kontekstu.
FWIW, używam wersji Spring 3.0.5 (również wypróbowany z 3.1.2, te same wyniki) z konstruktorem o.s.c.s.ClassPathXmlApplicationContext(String ...configLocations)
.
Mogę łatwo przekonwertować mój kod, aby użyć statycznego inicjalizatora, ale chcę zrozumieć, dlaczego Spring zachowa się w ten sposób. Czy to błąd?
EDIT: Niektóre dodatkowe dochodzenie wykazało, że
- Po kontekst aplikacji jest inicjowany, wszystkie kolejne wnioski do
context.getBean(Foo.class)
zawsze powrócić tą samą instancjęFoo
. - Zastąpienie
@Autowired
za pomocą setterów (około 20 zastosowań tego fasoli) wciąż powoduje powstanie wielu konstrukcji tego obiektu, ale wszystkie zależności są wstrzykiwane pod tym samym numerem .
Powyższe sugeruje, że jest to wiosenny błąd związany z implementacją @Autowired
. Zamierzam publikować na wiosennych forach społecznościowych i zamieszczać je tutaj, jeśli uda mi się uzyskać cokolwiek pożytecznego.
Może to być oczywiste, ale czy w grze jest tylko 1 JVM? Okrężne zależności? –
Tak, jest to tylko jedna maszyna JVM. Okrężne zależności - tak, ale uważam, że wyjaśniłem to w moim poście. – mindas
Widzę, ale co się dzieje, jeśli masz na przykład wstrzyknięcie konstruktora? Jak Spring ma rozwiązać ten problem? –