我正在使用Guice和Java。
我想更改接口的实现取决于我的代码的入口点(哪个主类)
我想在每个入口点设置不同的System.property
并创建新的提供程序以初始化其中一个实现。
有没有办法使用Guice初始化图而不是我自己构建实现?
public class AltsMatcherProvider implements Provider<IAltsPairsMatcher> {
@Override
public IAltsPairsMatcher get() {
switch (System.getProperty(regressionType)) {
default:
case "regular": {
return new AltsPairsMatcherByName();
}
case "bidi": {
return new AltsPairsMatcherBySegments();
}
}
}
}
答案 0 :(得分:2)
传统的方法是将Provider
个特定实现注入通用接口的Provider
:
public class AltsMatcherProvider implements Provider<IAltsPairsMatcher> {
@Inject Provider<AltsPairsMatcherByName> regularProvider;
@Inject Provider<AltsPairsMatcherBySegments> bidiProvider;
@Override
public IAltsPairsMatcher get() {
switch (System.getProperty(regressionType)) {
default:
case "regular": {
return regularProvider.get();
}
case "bidi": {
return bidiProvider.get();
}
}
}
}
(或者使用构造函数注入而不是@Inject
ed字段;我正在从移动设备回答,所以选择了最小的代码)
答案 1 :(得分:0)
我在提供商
中使用了@Inject
@Inject
public AltsMatcherProvider(ListUtils listUtils, SegmentsIdsChecker segmentsIdsChecker) {
this.listUtils = listUtils;
this.segmentsIdsChecker = segmentsIdsChecker;
}
@Override
public IAltsPairsMatcher get() {
final String routingType = System.getProperty(Constants.routingType);
if (routingType == null)
{
return new AltsPairsMatcherByName(listUtils, segmentsIdsChecker);
}
switch (routingType) {
default:
case "regular": {
return new AltsPairsMatcherByName(listUtils, segmentsIdsChecker);
}
case "bidi": {
return new AltsPairsMatcherBySegments(listUtils, segmentsIdsChecker);
}
}
}
}
答案 2 :(得分:0)
提供商在创建时会被注入,因此您可以要求Injector
或Provider
类型AltsPairsMatcherByName
和AltsPairsMatcherBySegments
。
但是......我不相信自定义Provider
是正确的方法。这听起来像是custom annotations/@Named的案例或Robot Legs上的变体。
答案 3 :(得分:0)
在这种情况下,我会实现两个独立的模块:
public void configure() {
bind(IAltsPairsMatcher.class).to(AltsPairsMatcherByName.class);
}
...
public void configure() {
bind(IAltsPairsMatcher.class).to(AltsPairsMatcherBySegments.class);
}
然后根据系统属性或命令行标志选择要安装的模块:
class ParentModule {
public void configure() {
switch (System.getProperty(Constants.routingType)) {
case NAME:
install(new ByNameModule());
break;
case SEGMENT:
install(new BySegmentsModule());
break;
}
}
}
这样可以保持一个很好的属性,即对象图可以静态地解析到注入器,并且肯定不会在运行时更改。只需检查您的模块,您就应该能够确定特定实现的来源。这是在Guice错误消息idiom中编码的,它显示了从原始父级到绑定的一系列模块。您也可以在switch语句中内联绑定,重要的是在创建注入器时解决所有问题。