Java 为什么Guice阻止绑定到提供程序?
最近,当我在谷歌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
@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) { ... }