问题
I am trying to be able to have this in my code
@Inject
private Map<String, Provider<Processor>> providers;
I was trying but this code does not compile
MapBinder<String, Provider<Processor>> mapbinder = MapBinder.newMapBinder(binder, String.class, Provider<Processor>.class);
mapbinder.addBinding("splineV1Beta").to(SplineProcessor.class);
mapbinder.addBinding("invertV1Beta").to(InvertProcessor.class);
This code fails on startup in that it can't bind my Map
MapBinder<String,Processor> mapbinder = MapBinder.newMapBinder(binder, String.class, Processor.class);
mapbinder.addBinding("splineV1Beta").to(SplineProcessor.class);
mapbinder.addBinding("invertV1Beta").to(InvertProcessor.class);
How do I setup the bindings correctly here?
NOTE: I am looking for something easy too so developers just add one line every time we have a new processor.(I am hoping I don't have to add one line + some factory interface...should be a way, but I have tried other things in addition to above with TypeLiteral and toProvider() method as well).
MORE INFO: okay, I found out if I have the below line(but do not call addBinding at all) Guice will actually startup which is good, but all the addBinding().to method signatures are now wrong as they want a
Provider<? extends Provider<Processor>>
//This below line ends up with mabbinder2.addBinder().to() wanting the above param type?
MapBinder<String, Provider<Processor>> mapbinder2 = MapBinder.newMapBinder(binder, stringLit, list);
RADICALLY change my thinking and I try injecting something like this(hoping that map.get("xxx") creates new instances every time...
@Inject
private Map<String, Processor> providers;
and I bound it like this but unfortunately, the map is always returning the same instance :(...
MapBinder<String, Processor> mapbinder = MapBinder.newMapBinder(binder, String.class, Processor.class);
mapbinder.addBinding("splineV1Beta").toProvider(new TypeLiteral<Provider<SplineProcessor>>() {;});
mapbinder.addBinding("invertV1Beta").toProvider(new TypeLiteral<Provider<InvertProcessor>>() {;});
EDIT: according to this doc http://google-guice.googlecode.com/svn/trunk/latest-javadoc/com/google/inject/multibindings/MapBinder.html you can have a
MapBinder<String, Snack> and inject a Map<String, Provider<Snack>>
but when I do that(with a private field), I get the following....(whereas when I change to my other solution but don't call mapbinder.addBinding, it binds and works just fine)...
1) No implementation for java.util.Map<java.lang.String,
javax.inject.Provider<controllers.modules2.framework.Processor>> was bound.
Do I have to use constructor injection for this to work like their example? I am in an abstract class so that would be very inconvenient to change 10 classes :(.
thanks, Dean
回答1:
Though Guice seems to be very good about using JSR-330 annotations interchangeably, it seems that Multibindings hides the Provider
type within a Map
and therefore may be expecting to inject a java.util.Map<java.lang.String, com.google.inject.Provider<...>>
instead. I haven't been able to reproduce your problem, but try that and see if it helps.
Side note: If you want to avoid changing it in code everywhere, you can hackishly bind a provider of Map<String, javax.inject.Provider<Foo>>
to something that takes in the multibinder-created Map<String, com.google.inject.Provider<Foo>>
. If I'm right and this is the problem, you can fix it one place rather than bouncing between javax.inject
and com.google.inject
everywhere.
回答2:
If you want Map<String, Provider<Processor>>
at the injection point, the way to bind it is:
MapBinder<String, Processor> mapbinder = MapBinder.newMapBinder(binder, String.class, Processor.class);
mapbinder.addBinding("splineV1Beta").to(SplineProcessor.class);
mapbinder.addBinding("invertV1Beta").to(InvertProcessor.class);
You would use toProvider()
if you are supplying a custom provider, which you are not, i.e. you are merely trying to use the implicit underlying provider.
来源:https://stackoverflow.com/questions/14833777/guice-multibinder-with-providers