2014-06-18 39 views
2

最近,當我與谷歌吉斯發揮各地,我試圖做這樣的事情:爲什麼Guice禁止綁定到提供者?

@Override 
protected void configure() { 
    ... 
    bind(Provider.class).to(ViewFactory.class); 
    ... 
} 

其中ViewFactory是:

public class ViewFactory implements Provider<SomeType> {...} 

當然,吉斯沒有讓我這樣做returing錯誤:

1) Binding to Provider is not allowed. 
{stacktrace} 

爲什麼不能綁定到提供程序的原因是什麼?

回答

7

我想這是因爲Provider界面非常特別的吉斯。實際上,所有內部機制都是以供應商的角度來實施的。

此外,這可能會產生歧義。如果綁定到提供商是可能的:

bind(SomeClass.class).to(SomeClassImpl1.class); 
bind(new TypeLiteral<Provider<SomeClass>>() {}).to(() -> new SomeClassImpl2()); 

然後guice應該在這裏注入?

@Inject 
OtherClass(Provider<SomeClass> someClassProvider) { ... } 

它應該是它返回SomeClassImpl1(因爲第一結合的;記住,直接注射和提供商注射是在吉斯互換)的提供者還是應返回SomeClassImpl2(因爲第二結合)的提供者?

它確實是多餘的。因爲無論實際綁定如何,您都可以注入SomeClassProvider<SomeClass>,您可以將該類本身綁定到其提供程序:

bind(SomeClass.class).toProvider(() -> new SomeClassImpl()); 

// Either of the following will work 
@Inject 
OtherClass1(Provider<SomeClass> someClassProvider) { ... } 

@Inject 
OtherClass2(SomeClass someClass) { ... } 
2

Provider是一個特例。 Guice在Provider背後做了很多事情,所以他們完全禁止綁定到Provider類。一個例子是範圍設定:您的自定義Provider可能每次都會調用new,但是如果您在Singleton範圍內創建提供程序,則不應該發生這種情況。所以Guice實際上並沒有注入你的提供者,它注入了一個包裝版本。這就是爲什麼他們直接禁止綁定到Provider.class。下面是一個代碼示例:

import com.google.inject.*; 
import com.google.inject.name.*; 

public class ProviderBindExample { 
    public static class ProvModule extends AbstractModule { 

    @Override 
    protected void configure() { 
     bind(Foo.class).toProvider(FooProvider.class); 
     bind(Foo.class).annotatedWith(Names.named("singleton")) 
      .toProvider(FooProvider.class) 
      .in(Singleton.class); 
    } 
    } 

    public static interface Foo { } 

    public static class FooProvider implements Provider<Foo> { 
    @Override 
    public Foo get() { 
     return new Foo() {}; 
    } 
    } 

    public static class SomeClass { 
    @Inject public Provider<Foo> provider; 
    @Inject @Named("singleton") public Provider<Foo> singletonProvider; 
    } 

    public static void main(String... args) { 
    Injector inj = Guice.createInjector(new ProvModule()); 
    SomeClass s = inj.getInstance(SomeClass.class); 
    System.out.println("Provider class = " + s.provider.getClass()); 
    System.out.println("Singleton provider class = " + s.singletonProvider.getClass()); 

    Foo first = s.provider.get(); 
    Foo second = s.provider.get(); 

    System.out.printf("regular scope: objects are %s%n", first == second ? "the same" : "different"); 

    first = s.singletonProvider.get(); 
    second = s.singletonProvider.get(); 

    System.out.printf("singleton scope: objects are %s%n", first == second ? "the same" : "different"); 
    } 
} 

輸出:

Provider class = class com.google.inject.internal.InjectorImpl$4 
Singleton provider class = class com.google.inject.internal.InjectorImpl$4 
regular scope: objects are different 
singleton scope: objects are the same 
相關問題