如何将Guice的AssistedInject工厂与服务加载器一起使用?

问题描述 投票:1回答:1

在我的guice模块中,我有多个工厂,如下图所示。

install(new FactoryModuleBuilder().implement(SportsCar.class,Ferrari.class).build(FerrariFactory.class));
install(new FactoryModuleBuilder().implement(LuxuryCar.class,Mercedes.class).build(MercedesFactory.class));

这两个工厂都有下面的create方法,它需要一个assisted元素。

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;
} 

在同一个类里

if(type.equals("ferrari"))
    ferrariFactory.create(partsElement);
else if (type.equals("mercedes"))
    mercedesFactory.create(partsElement);
...

现在,什么 我试图让这个CarChooser类的扩展是开放的,但修改是封闭的,也就是说,如果我需要添加另一个工厂,我不应该把它声明为一个变量+添加到构造函数中+为相应的新类型添加另一个if子句。 我打算在这里使用ServiceLoader,并声明一个接口CarFactory,这个接口将由所有工厂(如FerrariFactory、MercedesFactory等)实现,所有实现都有一个getCarType方法。但我如何使用Service Loader调用创建方法?

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没有绑定到任何实现上。我在这里应该有什么来将它绑定到用 FactoryModuleBuilder 声明的正确的 Assisted Inject Factory ?

java dependency-injection guice guice-3
1个回答
0
投票

所以,使用MapBinder与generics一起使用就是解决方案。

    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.comgoogleguiceissues904。

希望能帮到你。

更多关于解决方案的细节。

http:/crusaderpyro.blogspot.sg201607google-guice-how-use-mapbinder.html。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.