2016-03-15 82 views
1

我的課程取決於一些服務需要少量參數然後進行網絡調用,目前我正在傳遞這些參數,然後通過注入我的課堂的工廠創建這些服務。我需要將這些服務作爲依賴注入,我知道我可以爲它們創建提供程序,但在大多數示例中,我發現提供程序通常會綁定到像serveraddres等固定值,但我需要在此期間給出值運行。如何使用自定義參數配置提供者?

下面是我的示例代碼:

public SomeClass { 
    private final SomeFactory someFactory; 

    @Inject 
    SomeClass(SomeFactory factory) { 
     someFactory = factory; 
    } 

    public Foo getFoo(String fooId) { 
     FooService fooService = someFactory.getFooService(fooId); 
     return fooService.getFoo(); 
    } 

} 

我需要做的是:

public SomeClass { 
    private final FooService fooService; 

    @Inject 
    SomeClass(FooService fooService) { 
     this.fooService = fooService; 
    } 

    public Foo getFoo(String fooId) { 
     return fooService.getFoo(); 
    } 

} 

更新1

使用情況更加清晰:

@Provides 
    @RequestScoped 
    public SomeService provideSomeService(Dep1 dep1, String code) throws IOException { 
    return new SomeService.Builder() 
     .withApplicationName("Foo") 
     .setCode(code) 
     .build(); 
    } 

在這裏,code可以是null默認情況下,當需要時我可以給它一些價值。

我可以以某種方式在提供程序創建之前將參數傳遞給提供程序嗎?

+1

你可以做到這一點只有在'code'可以注射:靜態(因爲一些配置),或通過一些提供者(在你的情況下,因爲'代碼'是恆定的,但與會話範圍有關) –

+0

@JérémieB如果我們在同一頁面上,那麼我們不能在Guice中用動態值做任何事情在這種情況下,我需要重組我的應用程序,對吧? – vivek

回答

1

如果你有你的價值綁定(這裏,code是一個沒有綁定註釋的字符串),那麼你的更新1正是代碼的樣子。

在實踐中,有一些差異:

  • 常數像intString值通常與結合註解,無論@Named或自定義註釋。
  • 如果您需要在Guice初始化後將值注入到對象圖中,但具有足夠深的對象圖,依賴注入仍然是一個好主意,則可以創建一個child injector。通過這種方式,您可以在一個操作或對象中訪問@Named("code") String,但不能跨越整個Guice應用程序。
  • 如果您的code的值足夠動態以至於無法通過Guice作爲自己的關鍵字提供,那麼您必須通過使用某種工廠來傳遞它。對於一個基於Builder的對象,我會說你的SomeFactory實現是我想出的最好的。

如果您不需要使用Builder,並且可以讓Guice根據您的字段或構造函數參數創建對象,則可以通過代碼生成Factory。

  • Guice可以通過FactoryModuleBuilder爲您生成一個工廠,其功能名爲"assisted injection"
  • 谷歌的其他工具,AutoFactory,將代碼生成一個在Guice和Dagger中工作的工廠實現。 (它是捆綁爲「自動」,其中包括一個名爲AutoValue模型對象發生器,還生成註釋實現。)

我把孩子噴射器的小規模示威活動,並在my other SO answer here輔助注射。

+0

按需要我的意思是運行時間我可以改變代碼的價值,但我認爲這不是一個好主意。我認爲guice只適用於靜態依賴。 – vivek

0

這裏最好的辦法是參數化模塊,並通過一個供應商,你在運行時創建的參數:

public class MyModule extends AbstractModule { 
    private final String code; 

    public MyModule(String code) { 
    this.code = code; 
    } 

    @Override public void configure() { 
    Provider<Dep1> depProvider = getProvider(Dep1.class); 
    bind(SomeService.class) 
     .toProvider(() -> new SomeService.Builder() 
      .withApplicationName("Foo") 
      .withDep(depProvider.get()) 
      .setCode(code) 
      .build()) 
     .in(RequestScoped.class); 
    } 
} 
+0

此代碼在模塊初始化期間正在設置,因此我們無法在運行時重置代碼。 – vivek

+0

好吧,無論如何字符串是不可改變的,所以它們在運行時不能改變。也許傳入'AtomicReference '並依賴於它,在運行時更改它?我想說這是一個很大的反模式,而不是Guice應該如何使用。考慮讓那些依賴於不斷變化的字符串的東西調用一些其他服務來獲得它的當前值。 – Cardano

+0

假設依賴圖中有一個服務可以根據http請求等參數具有不同的行爲,那麼你可以用guice做到這一點嗎? – vivek

相關問題