2009-07-28 9 views
8

Mam do czynienia ze starszą bazą kodu, w której klasa, która nie jest okablowana na wiosnę, musi uzyskać klasę, która jest podłączona na wiosnę zgodnie z. Miałem nadzieję, że utworzę klasę fabryczną, która została podłączona podczas uruchamiania, a następnie mógłbym po prostu wywołać metodę getInstance() w celu uzyskania obiektu przewodowego. Jaki jest najlepszy sposób na zrobienie tego?Spring Wire a Static Class

przykład:

public class LegacyA { 
    public void doSomething() { 
     ... 
     Foo foo = FooFactory.getInstance(); 
     ... 
    } 
} 

public class FooFactory { 
    private static Foo foo; 

    public static Foo getInstance() { 
     if (foo == null) throw new IllegalStateException(); 
     return foo; 
    } 
} 

trzeba FooFactory być okablowana na starcie, aby LegacyA można łatwo wywołać getInstance() tak, że powraca wystąpienie foo (który jest również fasoli zdefiniowane w kontekście aplikacji).

<bean id="legacyA" class="LegacyA"/> 

<bean id="foo" class="Foo"/> 

<!-- I need this bean to be injected with foo so that the FooFactory can return a foo --> 
<bean id="fooFactory" class="FooFactory"/> 

Edit: Musiałem ponownie pracować mój przykład trochę jak mam to nieco confuzzled we własnej głowie ...

+0

Jak Foo jest wstrzykiwany do FooFactory? Seter, konstruktor, ...? – wds

Odpowiedz

10

Korzystanie statykę tak naprawdę idzie na przekór Spring IoC, ale jeśli naprawdę mieć z nich korzystać, to chciałbym zaproponować napisanie proste wiosna hak która przyjmuje Foo i wstrzykuje go do FooFactory, np

public class FooFactoryProcessor implements InitializingBean { 

    private Foo foo; 

    public void setFoo(Foo foo) { 
     this.foo = foo; 
    } 

    public void afterPropertiesSet() throws Exception { 
     Foofactory.setFoo(foo); 
    } 
} 

I w XML:

<bean id="foo" class="Foo"/> 

<bean class="FooFactoryProcessor"> 
    <property name="foo" ref="foo"/> 
</bean> 

Nie ma potrzeby modyfikowania Foo lub FooFactory

+0

zgodził się ze swoim statycznym komentarzem. Normalnie nigdy nie podążałbym tą trasą, jednak starszy kod używa tej klasy statycznej w każdym miejscu i najlepszym sposobem na zahaczenie tego nowego obiektu wiosennego bez zerwania istniejącego kodu jest utrzymywanie połączeń ze starą klasą statyczną i posiadanie statycznego klasy wykorzystaj nowy i ulepszony obiekt przewodowy sprężynowy. – digiarnie

+2

Dlaczego po prostu nie pozwól wiosną zarządzać FooFactory bezpośrednio. Tak naprawdę nie potrzebujesz abstrakcji, którą jest "FooFactoryProcessor". Możesz dodać niestatyczny kreator właściwości do FooFactory, aby ustawić na nim foo. –

+0

To prawda, tak, ale szedłem wzdłuż linii najmniejszej liczby zmian w dotychczasowym kodzie, który wydawał się być PO po. – skaffman

1

jest zdefiniowanie fasoli jako singleton w konfiguracji wiosennym użytkowania tutaj? Następnie można go wstrzyknąć do LegacyB za pomocą iniekcji właściwości lub konstruktora (moją preferencją jest ta ostatnia), a następnie dostępna jest tylko jedna instancja.

EDYCJA: Re. twoje zmienione pytanie (!) Nie wiem, dlaczego po prostu nie wstrzykujesz Foo raz jako singleton do swojej fabryki. Zauważ również, że możesz użyć metody getInstance() poprzez konfigurację Spring za pomocą factory-method i utrzymywać wstrzyknięcie przez wszystkie klasy.

+0

Przepraszamy za to, że trzeba nieco zmienić to pytanie. Nie zdawałem sobie sprawy, dopóki trochę później nie miałem w głowie całego pytania. – digiarnie

+0

Dzięki za heads up. To nie jest problem. Odpowiednio zmodyfikowana odpowiedź. –

1

Oprócz skaffman na odpowiedź trzeba być bardzo ostrożnym, aby inicjalizacji.

Podczas korzystania z fasoli Spring tylko framework automatycznie wykryje kolejność inicjowania. Jednak, gdy robisz triki singleton, może się to zepsuć, jeśli nie będziesz ostrożny.

Innymi słowy, upewnij się, że LegacyA nie może zostać uruchomiony przed zakończeniem ładowania kontekstu aplikacji.