Java 为什么Guice阻止绑定到提供程序?

Java 为什么Guice阻止绑定到提供程序?,java,dependency-injection,guice,Java,Dependency Injection,Guice,最近,当我在谷歌Guice上玩的时候,我试着做这样的事情: @Override protected void configure() { ... bind(Provider.class).to(ViewFactory.class); ... } 其中ViewFactory为: public class ViewFactory implements Provider<SomeType> {...} 无法绑定到提供程序的原因是什么?提供程序是一种特殊情况。Gu

最近,当我在谷歌Guice上玩的时候,我试着做这样的事情:

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

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

无法绑定到提供程序的原因是什么?提供程序是一种特殊情况。Guice在幕后使用
Provider
做了很多事情,所以他们只是完全禁止绑定到
Provider
类。一个例子是作用域:您的自定义
提供程序每次都可能调用
new
,但如果您在单例范围内创建提供程序,则不应发生这种情况。所以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");
  }
}

我想这是因为
提供者
接口对于Guice来说非常特殊。事实上,它的所有内部机制都是根据提供者来实现的

此外,这可能造成歧义。如果可以绑定到提供程序:

bind(SomeClass.class).to(SomeClassImpl1.class);
bind(new TypeLiteral<Provider<SomeClass>>() {}).to(() -> new SomeClassImpl2());
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
bind(SomeClass.class).to(SomeClassImpl1.class);
bind(new TypeLiteral<Provider<SomeClass>>() {}).to(() -> new SomeClassImpl2());
@Inject
OtherClass(Provider<SomeClass> someClassProvider) { ... }
bind(SomeClass.class).toProvider(() -> new SomeClassImpl());

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

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