问题
I have the following problem:
@Inject
MyClass(Service service) {
this.service = service;
}
public void doSomething() {
service.invokeSelf();
}
I have one module
bind(service).annotatedWith(Names.named("serviceA").to(ServiceAImpl.class);
bind(service).annotatedWith(Names.named("serviceB").to(ServiceBImpl.class);
Now my problem is I want to allow user to dynamically choose the injection on runtime base through command line parameter.
public static void Main(String args[]) {
String option = args[0];
.....
}
How could I do this? Do I have to create multiple modules just to do this?
回答1:
If you need to choose repeatedly at runtime which implementation to use the mapbinder is very appropriate.
You have a configuration like:
@Override
protected void configure() {
MapBinder<String, Service> mapBinder = MapBinder.newMapBinder(binder(), String.class, Service.class);
mapBinder.addBinding("serviceA").to(ServiceAImpl.class);
mapBinder.addBinding("serviceB").to(ServiceBImpl.class);
}
Then in your code just inject the map and obtain the right service based on your selection:
@Inject Map<String, Service> services;
public void doSomething(String selection) {
Service service = services.get(selection);
// do something with the service
}
You can even populate the injector with the selected service using custom scopes.
回答2:
I think what you actually want to do is something more like this:
public class ServiceModule extends AbstractModule {
private final String option;
public ServiceModule(String option) {
this.option = option;
}
@Override protected void configure() {
// or use a Map, or whatever
Class<? extends Service> serviceType = option.equals("serviceA") ?
ServiceAImpl.class : ServiceBImpl.class;
bind(Service.class).to(serviceType);
}
}
public static void main(String[] args) {
Injector injector = Guice.createInjector(new ServiceModule(args[0]));
// ...
}
回答3:
@ColinD has a good approach. I might suggest
public static void main(String[] args) {
Module m = "serviceA".equals(args[0]) ? new AServiceModule() : new BServiceModule();
Injector injector = Guice.createInjector(m);
// ...
}
The basic idea (in both answers) is if you can make your choices before the injector is built, you should always choose to do that.
As a matter of style, I like to keep the amount of logic inside a module to a minimum; but again, just a matter of style.
来源:https://stackoverflow.com/questions/7663618/guice-runtime-injection-binding-at-command-line