簡體   English   中英

通過提供值給提供者

[英]Giving a value to Provider in guice

我有以下提供者:

class MyProvider implements Provider<T> {
  private final ClassX objectX;
  private String name;

  @Inject
  public MyProvider(ClassX objectX) {
    this.objectX = objectX
  }

  T get() {
    // uses name and objectX to provide an object of T
  }
}

我的綁定看起來像這樣:

List<String> names;
for (String name : names) {
  bind(T.class).annotatedWith(Names.named(name))
    .toProvider(MyProvider.class)  // somehow set name in Provider
}

可從其他模塊訪問提供者的構造函數參數(並且從該模塊和該其他模塊創建注入器)。 我不知道如何將該名稱提供給提供商。 理想的方法是將其作為構造函數參數,並在綁定中設置其值。 知道如何實現這種目標嗎?

我認為您無法做到。 Guice綁定應始終是特定的; 每個綁定鍵(用於標識Guice在特定注入點必須注入的內容)由一個類型和一個可能的注釋組成: (Type, Optional<Annotation>) -> Implementation ,您不能在此處忽略該類型,這就是您所需要的真的在努力實現。

但是,Guice能夠綁定通配符類型,即可以將List<?>綁定到某個提供程序(使用TypeLiteral )。 因此,我想您應該能夠創建一個類,例如Cell<T> ,該類將包裝類型T的對象,並為Cell<?>創建綁定。 但是,那么您應該只能注入Cell<?> ,而不能注入像Cell<String>這樣的具體類型。 我不確定,也許Guice允許這種魔術,但是可能性不大。

順便說一句,您可以將任何參數傳遞給提供程序構造函數,並通過字段或方法提供其托管依賴項。 然后,您可以綁定到該提供程序的實例:

bind(Smth.class).toProvider(new SmthProvider("whatever"));

您可以在提供程序中動態查找對象。 但是,您必須提前知道所有可能需要的名稱。 這將起作用:

class MyProvider implements Provider<T> {
  private final Class<T> objectX;
  private final String name;

  @Inject
  public MyProvider(Class<T> objectX, String name) {
    this.objectX = objectX
    this.name = name;
  }

  public T get() {
    // uses name and objectX to provide an object of T
  }

}

然后是綁定-每個名稱需要一個提供程序實例:

List<String> names = ...;
for (String name : names) {
  bind(SpecificType.class).annotatedWith(Names.named(name))
    .toProvider(new MyProvider<SpecificType>(SpecificType.class, name));
}

如果要緩存結果或類似內容,則可能需要進行一些同步。

我終於做到了

class MyProvider implements Provider<T> {
  private ClassX objectX;
  private final String name;


  public MyProvider(String name) {
    this.name = name;
  }

  @Inject
  public setClassX(ClassX objectX) {
    this.objectX = objectX
  }

  T get() {
    // uses name and objectX to provide an object of T
  }
}

和綁定:

List<String> names;
for (String name : names) {
  MyProvider provider = new MyProvider(name);
  requestInjection(provider);
  bind(T.class).annotatedWith(Names.named(name))
    .toProvider(provider)  // somehow set name in Provider
}

requestInjection()方法是關鍵,它基本上將對象從同一注入器中注入到@Inject注釋的方法中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM