[英]Guice, FactoryModuleBuilder, multiple implementations, and generics
[英]Guice: One “Provider<T>” for multiple implementations
我有一個接口,有20個左右的注釋實現。 如果我知道在編譯時需要哪個,我可以注入正確的,但我現在需要根據運行時參數動態注入一個。
正如我對文檔的理解,我將不得不使用20個左右的Provider<T>
注入,然后使用我需要的那個,這對我來說似乎相當過分。 有沒有辦法讓像inst(Provider<T>).get(MyAnnotation.class)
綁定一個特定的實現,然后只有那個Provider
注入我的類?
在您的模塊中,將綁定加載到MapBinder
,然后使您的運行時參數也可注入。 此示例基於文檔中的示例:
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);
}
}
然后,在您的對象中,注入Map
和參數。 對於此示例,我假設您已為運行時參數綁定了java.util.Properties
:
@Inject
public MyObject(Map<String, Provider<Snack>> snackProviderMap, Properties properties) {
String snackType = (String) properties.get("snackType");
Provider<Snack> = snackProviderMap.get(property);
// etc.
}
注意,使用相同的MapBinder
您可以注入簡單的Map<String, Snack>
或Map<String, Provider<Snack>>
; Guice將兩者捆綁在一起。
如果您只想以編程方式獲取實例,則可以注入Injector。 這很少是一個好主意 - 注入Provider<T>
是一個更好的主意,尤其是為了測試 - 但是為了獲得綁定反射它是唯一的方法。
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));
}
}
如果你正在嘗試編寫一個帶參數的Provider,最好的方法就是寫一個小工廠。
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);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.