2012-10-30 70 views
2

我想用Guice作爲其中一個組件的非靜態實例方法(非託管bean應該可以訪問這個類)。我創造了這樣的事情:Guice的實例方法

public class LookupService { 

    @Inject 
    private static Provider<Injector> injector = null; 

    private final ILookup<IWS> lookup; 

    @Inject 
    public LookupService(ILookup<IWS> lookup) { 
     this.lookup = lookup; 
    } 

    public static LookupService instance() { 
    return injector.get().getInstance(LookupService.class); 
    } 

    public <T extends IWS> T lookup(Class<T> localInterface) { 
     return lookup.lookup(localInterface); 
    } 

}

你怎麼看待這樣的設計是什麼?有關於此的任何其他想法? (從非管理對象訪問託管bean)

回答

6

基本上,您要查找的模式稱爲「請求靜態注入」,並且存在Binder method dedicated to it。一旦你這樣做了,你的代碼看起來很像this example from the Guice docs

public class MainModule extends AbstractModule { 
    @Override public void configure() { 
    requestStaticInjection(LookupService.class); 
    } 
} 

public class LookupService { 

    /** This will be set as soon as the injector is created. */ 
    @Inject 
    static Provider<LookupService> provider = null; 

    private final ILookup<IWS> lookup; 

    @Inject 
    public LookupService(ILookup<IWS> lookup) { 
    this.lookup = lookup; 
    } 

    public static LookupService instance() { 
    return provider.get(); 
    } 

    public <T extends IWS> T lookup(Class<T> localInterface) { 
    return lookup.lookup(localInterface); 
    } 
} 

的幾個注意事項:

  • 雖然你仍然可以設置你的領域是private,請記住,這意味着你不能將其設置在測試(或將來非吉斯使用),而吉斯的私人領域訪問魔術。當使用注入字段時,我們經常使它們成爲私有包,然後將測試放在同一個包中。

  • 靜態注入通常被認爲是隻有在遷移到Guice時,或者當您使用其他代碼無法更改時才需要認可。如果可能,儘量避免全局狀態 - 即使這意味着僅生成FooBean數據並創建注入FooBeanService

  • 儘管您可以隨時隨地注入Injector,但如果您只是簡單地注入Provider<LookupService>,您可能會發現測試更容易。如果在運行時不知道需要什麼類型,則只注入Injector - 例如,如果通過將類文字傳遞到注入器以獲取實例來實現LookupService.lookup(...),則使用Injector

  • 事實上,很難從這裏說出來,但ILookup似乎很像Service Locator pattern,它解決了Guice用依賴注入解決問題的確切類型!如果是這樣的話,你可以重寫ILookup來使用Guice:只需刪除對LookupService.instance().lookup(Foo.class)的調用,而是創建一對匹配的@Inject static Provider<Foo> fooProviderrequestStaticInjection(FooUser.class)

希望幫助!

+0

好的答案! +1 –

+0

感謝您撰寫!我有類似的情況,你在第二點(舊代碼庫)中描述。隨着時間的推移,我將嘗試遷移到沒有靜態的方法。 這種方法恕我直言,但測試並沒有那麼糟糕,但需要Guice集成到測試框架。然後,當你想測試調用'LookupService.instance()'的類時,你需要在測試開始時爲它綁定模擬實現。 – sol25

+0

@ sol25請記住,基於Guice的系統測試是很好的,但是你也可能發現單元測試也是非常有用的,尤其是使用_mock_ LookupService的bean測試。放寬靜態字段可見性可能會讓你完全在大部分測試中跳過Guice。 –