2009-07-20 12 views
6

Mam aplikację, która ma wiele ekranów i każdy ekran jest wybierany za pomocą przycisku. Każdy ekran zawiera dość ciężkie komponenty, dlatego ważne jest, aby w pamięci był tylko ekran aktywacji - wszystkie inne powinny być dostępne do usuwania śmieci.Używanie getBean zamiast iniekcji metod wiosną

Aplikacja wykorzystuje sprężynowe dla kleju i obecnie przełącza to ekrany używając getBean():

//event handler for a specific button 
public void actionPerformed(Event e) { 
    setScreen((Screen) applicationContext.getBean("screen1")); 
} 

„screen1” jest prototypem fasola więc nowa instancja ekranu jest tworzony, gdy przycisk jest wciśnięty. Ponadto, setScreen() jest jedynym miejscem, w którym w aplikacji jest utrzymywane odniesienie do ekranu, więc poprzedni aktywny ekran będzie dostępny do usuwania śmieci. Jeszcze tego nie testowałem, ale spodziewam się, że to zadziała dobrze - bez nauki rakietowej tutaj!

Problem jest - po przeczytaniu this page o tym, dlaczego getBean() jest uważany za zły - zastanawiam się, czy istnieje bardziej idiomatyczny sposób osiągnięcia tych samych wyników przy usuwaniu zależności od getBean().

Przyjrzałem się iniekcji metod i wygląda na to, że wprowadzam złożoność z niewielką korzyścią. To kolejna koncepcja do nauki, więcej magii, dodaje zależność od CGLIB, itp. Jeśli naprawdę chcę usunąć zależność od Spring, mogę po prostu wprowadzić interfejs, który odsłania metodę getBean().

Czy metoda getBean() i metoda wstrzykiwania są jedynymi opcjami w moim przypadku lub czy coś przeoczyłem?

A jeśli tak, to czy getBean() jest naprawdę taki zły?

Odpowiedz

0

Czy rozważałeś podejście fabryczne?

public interface ComponentFactory<T> { 
    T create(); 
} 

public class ScreenFactory implements ComponentFactory<Screen> { 
    @Override 
    Screen create() { ... } 
} 

public class MyApp { 
    private ComponentFactory<Screen> screen1; 

    public void actionPerformed(Event e) { 
    setScreen(screen1.create()); 
    } 

    public void setScreen1(ComponentFactory<Screen> screen1) { 
    this.screen1 = screen1; 
    } 

    private void setScreen(Screen screen) { ... } 
} 

połączeniu z:

<bean id="screenFactory" class="com.myclass.ScreenFactory"/> 

<bean id="myapp" class="..."> 
    <property name="screen1" ref="screenFactory"/> 
</bean> 

Można oczywiście auto-wire powyższych.

Problem z tym, co robisz, polega na tym, że zarówno kodu źródłowego tworzonego komponentu, jak i powiązaniu implementacji z ApplicationContext. Jeśli kiedykolwiek będziesz musiał kpić i/lub testować swoje aplikacje/komponenty, to twoje życie będzie niesamowicie trudne. Powyższe rozwiązanie fabryczne sprawi, że będzie to banalne.

+0

W twoim rozwiązaniu, getbean() jest wywoływana w fabrycznej metodzie create(), prawda? –

+0

Niezupełnie. Zastąpiony jest metodą fabryczną, ale o wiele łatwiej jest kpić z powyższego interfejsu, niż ośmieszać kontekst aplikacji. Plus to wtykany. Ostatecznie jest to nieco prostsza implementacja metody Spring injection injection http://static.springsource.org/spring/docs/2.5.x/reference/beans.html # fasola-fabryka-lookup-method-injection – cletus

+0

Rozumiem, ale gdzie jest metoda tworzenia fabryki() z jej instancji ekranu? –

3

Wstrzyknięcie setera, wstrzyknięcie właściwości lub wstrzyknięcie konstruktora powoduje utworzenie luźno powiązanej aplikacji, która jest znacznie łatwiejsza do sprawdzenia przez kpiny. Zapobiega to także bezpośredniej zależności między klasami Spring (lub innymi kontenerami IoC). Kończy się to czystym ogólnym rozwiązaniem, gdy nie musisz ręcznie wywoływać funkcji getBean().

Myślę, że powinieneś się uporać z pojęciem konfigurowania zależności. "Magia" wcale nie jest magią i jest po prostu czymś, z czym poczujesz się komfortowo.

+0

Mam na myśli iniekcję metody za pomocą znacznika metody wyszukiwania, którą IMO różni się od "standardowej" iniekcji Dependency - jest to oddzielna funkcja, a która polega na AOP (a więc CGLIB) i co daje on nad fabryką (która cletus zademonstrował?) –

+0

Fabryka oddzieli twoją zależność od Wiosny, ale staje się tym, co moim zdaniem jest niepotrzebnym kodem do utrzymania. Co jest nie tak z AOP? AOP jest tylko szczegółem implementacji tego, jak Spring wykonuje DI. – geofflane

0

Jeśli chcesz się pozbyć getBean, rozważ użycie ServiceLocatorFactoryBean. Ale to, jak dobrze to działa, może zależeć od tego, skąd w aplikacji pochodzi napis "screen1".