2013-02-26 66 views
4

這個問題是,我試圖實現,並嘗試其他方式來解決這個問題,但沒有任何工作,所以這樣的延續遠。實例化每範圍/組單身 - 卡住在Guice依賴地獄

主要問題是這樣的。我有一個InterfaceAInterfaceB,暴露在API的不同部分。有跡象表明,實現這兩個接口,TestClassRealClass,使取決於我是否在測試或做別的事情,我可以做以下兩類:

bind(InterfaceA.class).to(TestClass.class); 
bind(InterfaceB.class).to(TestClass.class); 

,或者生產:

bind(InterfaceA.class).to(RealClass.class); 
bind(InterfaceB.class).to(RealClass.class); 

我對使用這些類的兩個要求:

  1. 我需要的TestClassRealClass同一實例綁定到所有InterfaceAInterfaceB;所以,像單身模式一樣,除了:
  2. 單身人士只針對特定範圍或子注射器,其中許多是在程序執行期間創建的。

缺省的無範圍方法會導致爲每個接口注入創建多個RealClass/TestClass實例。我不想這樣做,所以我試着用範圍,子注入器和其他方法來實現它。沒有奏效:

  • Child injector approach:我創建了一個新的注射器,並嘗試將TestClassRealClass綁定到該噴射器中的單一實例。問題是,TestClassRealClass正在使用在父注入器中配置,而since it's a singleton, it's already instantiated(除非在Stage.DEVELOPMENT中)。例如,在父注入器中無法綁定InterfaceATestClass,然後將其重新綁定爲子注入器中的單例。
  • 作用域方法:I create a custom scope和註釋TestClassRealClass。然後,我進入並退出該範圍以獲取該範圍內的單個實例。問題是我的代碼是多線程的,並且從一個線程改變了作用域會影響全局注入器可以看到的東西,並且可以創建其他實例。
  • 組合式兒童注射器和範圍方法。我試圖創建每次使用這個自定義範圍的子注入,但隨後在親代結合RealClass失敗

    No scope is bound to name.package.WhateverScope. 
    

    ,因爲它似乎堅持認爲WhateverScope是所有可用的時間,不只是在孩子注射器。

所有這些問題似乎是由於這樣的事實,我需要能夠配置是否在父用TestClassRealClass,但隨後以後能夠實例化它們,作爲一個單身,對於一組特定的對象。我正在拉我的頭髮,如何完成這項工作!

順便說一句,Guice示波器的文檔很糟糕,幾乎不可能理解。 This article是唯一一個將我帶到任何地方的人:

回答

4

抱歉在發佈後不到一個小時有點突破。

我似乎已經能夠通過略微濫用在http://code.google.com/p/google-guice/wiki/CustomScopes處提供的線程本地範圍實現來解決此問題。這似乎是一個不使用兒童注射器來解決這個問題的簡單方法。不過,我不確定它是否「正確」。我仍然會接受其他答案。

這就是我所做的。首先,我創建範圍的一個實例,它綁定到相應的註釋,並使其在噴射器可供選擇:

ThreadLocalScope scope = new ThreadLocalScope(); 
bindScope(ExperimentScoped.class, scope); 
bind(ThreadLocalScope.class).toInstance(scope); 

那麼,作爲文檔中說,我需要一個假提供商綁定爲每一個類型的這將在範圍播種的關鍵:

bind(SomeKey.class) 
    .toProvider(ThreadLocalScope.<SomeKey>seededKeyProvider()) 
    .in(ExperimentScoped.class); 
bind(SomeOtherKey.class) 
    .toProvider(ThreadLocalScope.<SomeOtherKey>seededKeyProvider()) 
    .in(ExperimentScoped.class); 

我也有,我想每個範圍內的不同的一些其他範圍,能夠對象,所以我結合這些呢。這些是上面的TestClassRealClass。可能有也SomeScopedClass這是與@ExperimentScoped註釋:

bind(InterfaceA.class).to(TestClass.class).in(ExperimentScoped.class); 
bind(InterfaceB.class).to(TestClass.class).in(ExperimentScoped.class); 

bind(SomeInterface.class).to(SomeScopedClass.class); 

最後,我可以使用的範圍,以創建不同的集合相互依存的對象,在來自不同線程並行。每個線程可以執行類似以下,即使他們使用的是同一個注射器:

ThreadLocalScope scope = injector.getInstance(ThreadLocalScope.class);  
scope.enter(); 

try { 
    // Seed the seed-able keys 
    scope.seed(SomeKey.class, keyInstance); 
    scope.seed(SomeOtherKey.class, otherKeyInstance);  

    SomeScopedClass instance = injector.getInstance(SomeScopedClass.class); 

    // Hooray! instance was injected with the seeds and created just for this scope! 
} 
finally { 
    scope.exit(); // Throws away the scope and referenced objects. 
} 

在我的情況,我可以完全拋棄範圍,因爲我不關心保持在一組對象的軌跡一旦他們連線正確,範圍。但是如果我想稍後再回到這個範圍並注入更多的對象,它可能不會起作用。

希望這有助於某人。 Guice範圍界定文件非常糟糕!