2009-07-20 54 views
6

我有一個具有多個屏幕的應用程序,每個屏幕都通過一個按鈕進行選擇。每個屏幕都包含相當重的組件,因此重要的是隻有激活屏幕在內存中 - 所有其他應該可用於垃圾收集。使用getBean而不是春季的方法注入

該應用程序使用Spring爲膠水和目前其切換使用的getBean屏幕():

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

「屏蔽1」是一個原型豆以使屏幕的一個新實例按下按鈕時被創建。另外,setScreen()是在應用程序中維護對Screen的引用的唯一位置,因此前面的活動屏幕將可用於垃圾收集。我還沒有測試過,但我希望它能正常工作 - 在這裏沒有火箭科學!

問題是 - 在讀取this page關於爲什麼getBean()被認爲是不好的 - 我想知道是否有一種更習慣性的方式來獲得相同的結果,同時消除對getBean()的依賴。

我已經看過方法注入和它在我看來引入複雜性沒有什麼好處。這是另一個學習的概念,更多的魔力,增加了對CGLIB的依賴,等等。如果我真的想刪除對Spring的依賴,我可以引入一個公開getBean()方法的接口。

是getBean()和方法注入在我的情況下唯一的選擇還是我錯過了什麼?

如果是這樣,是getBean()真的很糟糕?

回答

0

您是否考慮過工廠方法?

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

<bean id="myapp" class="..."> 
    <property name="screen1" ref="screenFactory"/> 
</bean> 
當然你也可以自動線的上方

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) { ... } 
} 

聯合。

你正在做的事情的問題是,它硬編碼你正在實例化的bean,並將你的實現綁定到ApplicationContext。如果您需要模擬和/或單元測試您的應用程序/組件,那麼這會讓您的生活變得難以置信。上面的工廠解決方案將使其變得微不足道。

+0

因此,在您的解決方案中,在工廠create()方法中調用getbean(),對吧? – 2009-07-20 15:38:31

+0

不完全。它被工廠方法取代,但模擬上述接口要比模擬應用程序上下文容易得多。另外它是可插拔的。最終,這是Spring的方法注入http://static.springsource.org/spring/docs/2.5的稍微簡單的實現。x/reference/beans.html#beans-factory-lookup-method-injection – cletus 2009-07-20 15:44:13

3

安裝程序注入,屬性注入或構造函數注入都會創建一個鬆散耦合的應用程序,通過嘲諷進行測試非常容易。它還可以防止您的任何類對Spring(或其他IoC容器)類具有直接依賴關係。當您不必手動調用getBean()時,它最終只是一個更清潔的整體解決方案。

我認爲你應該對配置依賴關係的概念感到滿意。這個「魔術」根本就不是魔術,而只是當你使用它時你會感到舒服的東西。

0

如果您只是想擺脫getBean,請考慮使用ServiceLocatorFactoryBean。但是,這對你的工作效果可能取決於字符串「screen1」來自你的應用程序的位置。