java - 如何使用 Guice 的 AssistedInject 工厂和服务加载器?

标签 java dependency-injection guice guice-3

在我的 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 类中,我获得了 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 类对扩展开放,但对修改关闭。也就是说,如果我需要添加另一个工厂,我不必将其声明为变量+将其添加到构造函数+为相应的新类型添加另一个 if 子句。我计划在这里使用 ServiceLoader 并声明一个 CarFactory 接口(interface),该接口(interface)将由所有工厂(例如 FerrariFactory、MercedesFactory 等)实现,并且所有实现都将具有 getCarType 方法。但是如何使用 Service Loader 调用 create 方法呢?

ServiceLoader<CarFactory> impl = ServiceLoader.load(CarFactory.class);

for (CarFactory fac: impl) {
     if (type.equals(fac.getCarType()))
         fac.create(partsElement);
     }
}

如果有效的话,这是正确的方法(我什至不确定这是否有效)。或者有更好的方法来做同样的事情吗?

感谢帖子的第一条评论,我知道我想使用 MapBinder 。我写了一个 CarFactory,它由 FerrariFactory 和 MercedesFactory 扩展。所以我添加以下内容:

MapBinder<String, CarFactory> mapbinder = MapBinder.newMapBinder(binder(), String.class, CarFactory.class);

mapbinder.addBinding("Ferrari").to(FerrariFactory.class);
mapbinder.addBinding("Mercedes").to(MercedesFactory.class);

但是由于上述代码的 .to 部分是抽象类,我收到一个初始化错误,即 FerrariFactory 未绑定(bind)到任何实现。我应该在这里将其绑定(bind)到使用 FactoryModuleBuilder 声明的正确辅助注入(inject)工厂吗?

最佳答案

因此,使用 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

关于java - 如何使用 Guice 的 AssistedInject 工厂和服务加载器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38430121/

相关文章:

task - Guice:提供程序中的注入(inject)器

java - 如何在 JavaFX 中使用菜单栏中的 id?

java - CustomRepositoryImpl 中的 Autowiring bean 为 null

java - 在 Eclipse 中,动态布局中弹出的文本链接

c# - Service Fabric Actor 服务依赖注入(inject)和 Actor 事件

asp.net-mvc - 如何访问 Controller 外部的 RequestContext?

java - 即使获取 204 作为 HTTP 状态代码,实体也不会保存在数据库中

Guice:在这种情况下,如何在模块中配置 @Provides 和 @Singleton?

java - 如何在GWT CellTree中选择父节点时选择所有子节点?

java - 非 ASCII 字符不显示