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

Is there a way to use Guice initialization graph in a custom provider instead of me constructing the implementations myself

我在 Java 中使用 Guice。

我想根据我代码的入口点更改接口的实现(主要class)

我想在每个入口点设置不同的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();
            }
        }
    }
}

我在提供商中使用了@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);
        }
    }
}

}

这样做的传统方法是将特定实现的 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();
            }
        }
    }
}

(或者使用构造函数注入而不是 @Injected 字段;我是通过移动设备回答的,所以只使用了最少的代码)

提供程序在创建时被注入,因此您可以请求 InjectorProvider 类型 AltsPairsMatcherByNameAltsPairsMatcherBySegments.

但是...我不认为自定义 Provider 是解决此问题的正确方法。这听起来像是 custom annotations/@Named OR a variant on the Robot Legs.

的情况

在这种情况下,我将实现两个独立的模块:

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 错误消息习语中进行了编码,它向您展示了从原始父级一直到绑定的模块链。您也可以只在 switch 语句中内联绑定,重要的是一切都在注入器创建时解决。