簡體   English   中英

Guice @Provides方法與提供者類

[英]Guice @Provides Methods vs Provider Classes

我正在研究一個有很多注射的相當大的項目。 我們目前正在使用一個為每個需要一個注入實現Provider的類,它們大多數都有一行get方法。

每次我需要一個新的提供者時,創建一個新類就開始變得煩人。 使用提供程序類而@Provides我的Module @Provides方法有什么好處,反之亦然?

據我所知,它們與大多數簡單案例完全相同。

/**
 * Class-style provider.
 * In module: bind(Foo.class).annotatedWith(Quux.class).toProvider(MyProvider.class);
 */
class MyProvider implements Provider<Foo> {
  @Inject Dep dep;  // All sorts of injection work, including constructor injection.

  @Override public Foo get() {
    return dep.provisionFoo("bar", "baz");
  }
}

/**
 * Method-style provider. configure() can be empty, but doesn't have to be.
 */
class MyModule extends AbstractModule {
  /** Name doesn't matter. Dep is injected automatically. */
  @Provides @Quux public Foo createFoo(Dep dep) {
    return dep.provisionFoo("bar", "baz");
  }

  @Override public void configure() { /* nothing needed in here */ }
}

在任何一種樣式中,Guice都允許您注入FooProvider<Foo> ,即使該鍵綁定到類或實例也是如此。 如果直接獲取實例,Guice會自動調用get如果不存在,則創建隱式Provider<Foo> 綁定注釋在兩種樣式中都有效。

@Provides的主要優點是緊湊性,特別是與匿名內部Provider實現相比。 但請注意,在某些情況下,您可能希望使用Provider類:

  • 您可以使用構造函數參數創建自己的長期Provider實例,並將鍵綁定到這些實例而不是類文字。

     bind(Foo.class).toProvider(new FooProvisioner("bar", "baz")); 
  • 如果您使用的是與JSR 330(javax.inject)兼容的框架,則可以輕松綁定到javax.inject.Provider類或實例。 com.google.inject.Provider擴展了該界面。

     bind(Foo.class).toProvider(SomeProviderThatDoesntKnowAboutGuice.class); 
  • 您的提供商可能足夠復雜,可以考慮自己的類。 根據您的測試結構,以這種方式測試您的提供商可能更容易。

  • 提供者可以擴展抽象類。 使用@Provides方法執行此操作可能並不容易或直觀。

  • 您可以直接將多個密鑰綁定到同一個Provider。 每個@Provides方法只生成一個綁定,但您可以將其他鍵綁定到 (此處為@Quux Foo),並讓Guice進行第二次查找。

  • 如果您希望(例如)在不使用Guice作用域或綁定的情況下緩存或記憶實例,則提供程序很容易進行裝飾或換行。

     bind(Foo.class).toProvider(new Cache(new FooProvisioner("bar", "baz"))); 

重要提示 :雖然這對於Guice無法創建的類是一個很好的策略,但請記住,Guice可以為任何以任何方式bind Provider<T>自動創建和注入Provider<T> ,包括類名,密鑰,或實例。 除非有您自己的實際邏輯,否則無需創建顯式提供程序。

類的實例化方式也有所不同。 對於Eg:

public class GumProvider implements Provider<Gum> {

  public Gum get() {
    return new Gum();
  }
}

public class GumModule extends AbstractModule {

    protected void configure() {

        bind(Gum.class).toProvider(GumProvider.class);
        //bind(Gum.class).to(GumballMachine.class);
    }
}

public class GumballMachine {

    @Inject
    private Provider<Gum> gumProvider;

    Gum gum;


    public Gum dispense() {
        return gumProvider.get();
    }
}

public class App {

    public static void main(String[] args) {
      // TODO Auto-generated method stub
      Injector injector = Guice.createInjector(new GumModule());
      GumballMachine m = injector.getInstance(GumballMachine.class);
      System.out.println(m.dispense());
      System.out.println(m.dispense());


    }

}

這將創建一個每次調用的Gum實例。 然而,如果使用@Provides,則相同的Gum實例將被傳遞給兩個注射器

暫無
暫無

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

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