如何将 Guice 的 AssistedInject 工厂与服务加载器一起使用?
How to use Guice's AssistedInject factories along with service loader?
在我的 guice 模块中,我有多个工厂,如下所示:
install(new FactoryModuleBuilder().implement(SportsCar.class,Ferrari.class).build(FerrariFactory.class));
install(new FactoryModuleBuilder().implement(LuxuryCar.class,Mercedes.class).build(MercedesFactory.class));
两个工厂都有以下采用辅助元素的创建方法:
Ferrari create(@Assisted Element partsElement);
Mercedes create(@Assisted Element partsElement);
在 CarChooser class 中,我得到 Ferrari 或 Mercedes 的实例,如下所示:
@Inject
public CarChooser(FerrariFactory ferrariFactory , MercedesFactory mercedesFactory )
{
this.ferrariFactory = ferrariFactory;
this.mercedesFactory = mercedesFactory;
}
同class:
if(type.equals("ferrari"))
ferrariFactory.create(partsElement);
else if (type.equals("mercedes"))
mercedesFactory.create(partsElement);
...
现在,我正在尝试让这个 CarChooser class 对扩展开放但对修改关闭。即如果我需要添加另一个工厂,我不必将其声明为变量+将其添加到构造函数+为相应的新类型添加另一个 if 子句。 我打算在这里使用 ServiceLoader 并且声明一个将由所有工厂(例如 FerrariFactory、MercedesFactory 等)实现的接口 CarFactory,并且所有实现都将具有 getCarType 方法。但是如何使用 Service Loader 调用创建方法?
ServiceLoader<CarFactory> impl = ServiceLoader.load(CarFactory.class);
for (CarFactory fac: impl) {
if (type.equals(fac.getCarType()))
fac.create(partsElement);
}
}
如果可行的话,这是正确的方法(我什至不确定这是否可行)。或者有更好的方法来做同样的事情吗?
感谢 post 上的第一条评论,我知道我想使用 MapBinder 。我写了一个由 FerrariFactory 和 MercedesFactory 扩展的 CarFactory。所以我添加以下内容:
MapBinder<String, CarFactory> mapbinder = MapBinder.newMapBinder(binder(), String.class, CarFactory.class);
mapbinder.addBinding("Ferrari").to(FerrariFactory.class);
mapbinder.addBinding("Mercedes").to(MercedesFactory.class);
但是由于上述代码的 .to 部分是抽象的 class 我得到一个初始化错误,即 FerrariFactory 未绑定到任何实现。我应该在此处将其绑定到使用 FactoryModuleBuilder 声明的正确的 Assisted Inject Factory 吗?
因此,将 MapBinder 与泛型一起使用是解决方案。
install(new FactoryModuleBuilder().implement(SportsCar.class,Ferrari.class).build(FerrariFactory.class));
install(new FactoryModuleBuilder().implement(LuxuryCar.class,Mercedes.class).build(MercedesFactory.class));
MapBinder<String, CarFactory<?>> mapbinder = MapBinder.newMapBinder(binder(), new TypeLiteral<String>(){}, new TypeLiteral<CarFactory<?>>(){});
mapbinder.addBinding("ferrari").to(FerrariFactory.class);
mapbinder.addBinding("mercedes").to(MercedesFactory.class);
这里需要注意的重要一点是,这似乎仅在 Guice 3.0 + JDK 7 中受支持。对于 JDK 8,您需要 Guice 4.0!在 https://github.com/google/guice/issues/904
上发现了这个问题
希望对您有所帮助。
有关解决方案的更多详细信息:
http://crusaderpyro.blogspot.sg/2016/07/google-guice-how-to-use-mapbinder.html
在我的 guice 模块中,我有多个工厂,如下所示:
install(new FactoryModuleBuilder().implement(SportsCar.class,Ferrari.class).build(FerrariFactory.class));
install(new FactoryModuleBuilder().implement(LuxuryCar.class,Mercedes.class).build(MercedesFactory.class));
两个工厂都有以下采用辅助元素的创建方法:
Ferrari create(@Assisted Element partsElement);
Mercedes create(@Assisted Element partsElement);
在 CarChooser class 中,我得到 Ferrari 或 Mercedes 的实例,如下所示:
@Inject
public CarChooser(FerrariFactory ferrariFactory , MercedesFactory mercedesFactory )
{
this.ferrariFactory = ferrariFactory;
this.mercedesFactory = mercedesFactory;
}
同class:
if(type.equals("ferrari"))
ferrariFactory.create(partsElement);
else if (type.equals("mercedes"))
mercedesFactory.create(partsElement);
...
现在,我正在尝试让这个 CarChooser class 对扩展开放但对修改关闭。即如果我需要添加另一个工厂,我不必将其声明为变量+将其添加到构造函数+为相应的新类型添加另一个 if 子句。 我打算在这里使用 ServiceLoader 并且声明一个将由所有工厂(例如 FerrariFactory、MercedesFactory 等)实现的接口 CarFactory,并且所有实现都将具有 getCarType 方法。但是如何使用 Service Loader 调用创建方法?
ServiceLoader<CarFactory> impl = ServiceLoader.load(CarFactory.class);
for (CarFactory fac: impl) {
if (type.equals(fac.getCarType()))
fac.create(partsElement);
}
}
如果可行的话,这是正确的方法(我什至不确定这是否可行)。或者有更好的方法来做同样的事情吗?
感谢 post 上的第一条评论,我知道我想使用 MapBinder 。我写了一个由 FerrariFactory 和 MercedesFactory 扩展的 CarFactory。所以我添加以下内容:
MapBinder<String, CarFactory> mapbinder = MapBinder.newMapBinder(binder(), String.class, CarFactory.class);
mapbinder.addBinding("Ferrari").to(FerrariFactory.class);
mapbinder.addBinding("Mercedes").to(MercedesFactory.class);
但是由于上述代码的 .to 部分是抽象的 class 我得到一个初始化错误,即 FerrariFactory 未绑定到任何实现。我应该在此处将其绑定到使用 FactoryModuleBuilder 声明的正确的 Assisted Inject Factory 吗?
因此,将 MapBinder 与泛型一起使用是解决方案。
install(new FactoryModuleBuilder().implement(SportsCar.class,Ferrari.class).build(FerrariFactory.class));
install(new FactoryModuleBuilder().implement(LuxuryCar.class,Mercedes.class).build(MercedesFactory.class));
MapBinder<String, CarFactory<?>> mapbinder = MapBinder.newMapBinder(binder(), new TypeLiteral<String>(){}, new TypeLiteral<CarFactory<?>>(){});
mapbinder.addBinding("ferrari").to(FerrariFactory.class);
mapbinder.addBinding("mercedes").to(MercedesFactory.class);
这里需要注意的重要一点是,这似乎仅在 Guice 3.0 + JDK 7 中受支持。对于 JDK 8,您需要 Guice 4.0!在 https://github.com/google/guice/issues/904
上发现了这个问题希望对您有所帮助。
有关解决方案的更多详细信息:
http://crusaderpyro.blogspot.sg/2016/07/google-guice-how-to-use-mapbinder.html