[英]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都允許您注入Foo
和Provider<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.