Guice: One “Provider<T>” for multiple implementations

喜夏-厌秋 提交于 2019-12-01 12:17:02

Inject a MapBinder.

In your module, load the bindings into the MapBinder, then make your runtime parameters injectable as well. This example is based on the one in the documentation:

public class SnacksModule extends AbstractModule {
  protected void configure() {
    MapBinder<String, Snack> mapbinder
           = MapBinder.newMapBinder(binder(), String.class, Snack.class);
    mapbinder.addBinding("twix").to(Twix.class);
    mapbinder.addBinding("snickers").to(Snickers.class);
    mapbinder.addBinding("skittles").to(Skittles.class);
  }
}

Then, in your object, inject the Map and the parameter. For this example I will assume you've bound a java.util.Properties for your runtime parameters:

@Inject
public MyObject(Map<String, Provider<Snack>> snackProviderMap, Properties properties) {
  String snackType = (String) properties.get("snackType");
  Provider<Snack> = snackProviderMap.get(property);

  // etc.
}

Note, with the same MapBinder you can inject either a simple Map<String, Snack> or a Map<String, Provider<Snack>>; Guice binds both.

If all you want is to get an instance programmatically, you can inject an Injector. It's rarely a good idea--injecting a Provider<T> is a much better idea where you can, especially for the sake of testing--but to get a binding reflectively it's the only way to go.

class YourClass {
  final YourDep yourDep;  // this is the dep to get at runtime

  @Inject YourClass(Injector injector) {
    YourAnnotation annotation = deriveYourAnnotation();
    // getProvider would work here too.
    yourDep = injector.getInstance(Key.get(YourDep.class, annotation));
  }
}

If you're trying write a Provider that takes a parameter, the best way to express this is to write a small Factory.

class YourDepFactory {
  @Inject @A Provider<YourDep> aProvider;
  @Inject @B Provider<YourDep> bProvider;
  // and so forth

  Provider<YourDep> getProvider(YourParameter parameter) {
    if (parameter.correspondsToA()) {
      return aProvider;
    } else if (parameter.correspondsToB()) {
      return bProvider;
    }
  }

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