Injecting a generic factory in Guice

匿名 (未验证) 提交于 2019-12-03 01:25:01

问题:

The following code is an example of a factory that produces a Bar given a Foo. The factory doesn't care what T is: for any type T, it can make a Bar from a Foo.

import com.google.inject.*; import com.google.inject.assistedinject.*;  class Foo {   public void flip(T x) { System.out.println("flip: " + x); } }  interface Bar {   void flipflop(T x); }  class BarImpl implements Bar {   Foo foo;    @Inject   BarImpl(Foo foo) { this.foo = foo; }    public void flipflop(T x) { foo.flip(x); System.out.println("flop: " + x); } }  interface BarFactory {    Bar create(Foo f); }  class Module extends AbstractModule {   public void configure() {     bind(BarFactory.class)       .toProvider(            FactoryProvider.newFactory( BarFactory.class, BarImpl.class )                     );   } }  public class GenericInject {   public static void main(String[] args) {     Injector injector = Guice.createInjector(new Module());      Foo foo = new Foo();     Bar bar = injector.getInstance(BarFactory.class).create(foo);     bar.flipflop(0);   } } 

When I run the code, I get the following errors from Guice:

1) No implementation for BarFactory was bound.   at Module.configure(GenericInject.java:38)  2) Bar cannot be used as a key; It is not fully specified. 

The only reference I can find to generics in the Guice documentation says to use a TypeLiteral. But I don't have a literal type, I have a generic placeholder that isn't relevant to the factory at all. Any tips?

回答1:

One option is to just write the BarFactory boilerplate by hand:

class BarImplFactory implements BarFactory {   public  Bar create(Foo f) {     return new BarImpl(f);   } } 

The binding becomes

bind(BarFactory.class).to(BarImplFactory.class); 


回答2:

If you think of guice as a system of wiring similar to spring, then it doesn't really make sense to wire a generic instance. You're wiring specific instances to keys, so that when another instantiated class marks something with @Inject BarFactory you get the specific created instance.

Since your implementation is generic, you haven't provided enough information to inject a specific instance. Although I haven't used factoryprovider, my assumption is that you'll need to bind the Barfactory to a fully parameterized instance, e.g. BarImpl instead of BarImpl )

Incidentally since you're binding BarFactory.class if you want to bind multiple instances you're going to have to inflect them somehow, either by name, something like (haven't checked the syntax, but)

bind(BarFactory.class).annotatedWith(Names.named("name1"))       .toProvider(   or by generics, bind(BarFactory).toProvider... 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!