2011-11-08 71 views
8

我在理解Guice的單例實例如何工作時遇到了一些麻煩。我已閱讀可用的文檔(這裏 - http://code.google.com/p/google-guice/wiki/Scopes),但我仍然無法弄清楚一些事情:Guice渴望/懶惰的單例實例

1)我已經集成了Guice和Tomcat,並且我在ServletModule中設置了一些綁定:

bind(MyServlet.class).asEagerSingleton(); 
serve("myUrl").with(MyServlet.class); 
serve("myOtherUrl").with(MyOtherServlet.class); 

(其中MyOtherServlet類有它上面的@Singleton註解) 我在這裏的目的是爲了有兩個servlet,其中一個是熱切實例,而另一個則不是。然而,似乎「serve ... with ...」這一行自動實例化servlet對象,即使該類沒有被綁定爲一個急切的單例。 我上面提到的鏈接提到了在Stage.Development和Stage.Production下運行的Guice之間的區別 - 但是即使我明確使用了Stage.Development(這是默認的一個),這仍然發生。 有什麼辦法可以避免這種情況?

2)(繼續1)嘗試確保MyServlet首先實例化,即使所有servlet現在都急切實例化,我在創建一個Injector時修改了模塊的順序(和綁定語句),以便爲MyServlet首先出現。然而,我發現,它仍然得到比其他一些綁定(非servlet類的),這是形式的實例化後:

bind(MyInterface.class).to(MyClass.class).asEagerSingleton() 

即使那些其他綁定在modules /綁定順序出現較晚。 我仔細研究過它,發現Guice只是簡單地實例化了「bind ... to ... asEagerSingleton()」形式的綁定的單身人士,然後再執行「bind ... asEagerSingleton()」 ,所以我通過修改該行來解決它: bind(MyServlet.class).asEagerSingleton(); (MyServletDummyInterface.class).to(MyServlet.class).asEagerSingleton()

並且實際工作。不過,我寧願避免擁有一個虛擬接口來解決這個問題,所以我想知道是否有人有更好的解決方案。

3)我有兩個Guice模塊 - 一個ServletModule和一個AbstractModule。 的servlet模塊configureServlets()具有以下在它綁定:

serve("aUrl").with(SomeServlet.class); 

的AbstractModule的配置()具有以下綁定:

bind(SomeImpl.class).asEagerSingleton(); 
bind(SomeInterface.class).to(SomeImpl.class).in(Singleton.class); 

此外,該SomeServlet類有類型SomeInterface的注入字段,並在課堂上有一個@Singleton註解。

現在,人們會期望創建一個注入器後,SomeImpl類將被實例化,並且同一個實例將被注入到SomeServlet實例中。如前所述,以「serve ... with ...」語句爲界限的servlet似乎也被迫切實例化,但無論哪種方式,只應該有一個SomeImpl對象實例化。然而由於某種原因,我在做這件事時得到了兩個實例化的SomeImpl對象。 要解決它,我在配置兩條線混合()了一下,而不是上面我有下面幾行:

bind(SomeImpl.class).in(Singleton.class) 
bind(SomeInterface.class).to(SomeImpl.class).asEagerSingleton(); 

,然後它工作得很好,我得到的只有一個實例SomeImpl實例化。我真的不明白爲什麼交換機應該重要 - 我可以看到後一種方式是「更好的」,但我希望兩者都能正常工作,所以我只是想知道在這裏是否出現了問題。 ?



很抱歉的長度,
感謝您的幫助!

回答

7

1)沒有辦法避免這種情況,因爲Guice調用所有servlet的init()方法來初始化它自己的過濾器管道,並因此構建它們全部。如果你真的需要這樣懶惰的初始化邏輯,你應該把它放到servlet本身(或者使用一個分離的輔助類,或者......有很多方法,這取決於你的用例)。

2)通常說,Guice 的模塊聲明綁定,但沒有設計成具有精確實例化順序的引導程序定義。如果您需要這種定義的實例化順序,請按照所需順序自行創建對象,並通過bind(...).toInstance(...)將它們綁定。如果你需要在自建實例中注入,你可以使用requestInjection(...)(如果字段/方法注入是足夠的,對構造函數注入來說更麻煩)。

3)Guice的範圍適用於綁定鍵,而不是綁定值,Applying Scopes描述了爲什麼只有第二個示例按預期工作。

相關問題