有没有办法在自定义提供程序中使用Guice初始化图,而不是我自己构建实现

时间:2016-03-01 12:12:20

标签: java dependency-injection guice

我正在使用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();
            }
        }
    }
}

4 个答案:

答案 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)

提供商在创建时会被注入,因此您可以要求InjectorProvider类型AltsPairsMatcherByNameAltsPairsMatcherBySegments

但是......我不相信自定义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语句中内联绑定,重要的是在创建注入器时解决所有问题。