java - 防止覆盖 guice 中已经绑定(bind)的类

标签 java dependency-injection guice

我正在尝试重新使用具有多个提供程序的库中的 guice 模块,我想使用库中的几个提供程序并在我自己的模块中提供一些提供程序。

库模块 -

public class LibraryModule extends AbstractModule {

    @Override
    protected void configure() {
    }

    @Provides
    @Singleton
    @Named("dbCredentials")
    private AWSCredentialsProvider getCredentialsProvider(@Named("app.keySet") String keySet) {
        return new SomeCredentialsProvider(keySet);
    }

    @Provides
    @Singleton
    private AmazonDynamoDB getDynamoDBClient(@Named("dbCredentials") AWSCredentialsProvider credentialsProvider,
                                             @Named("aws.region") String region) {

        return AmazonDynamoDBClientBuilder.standard()
                                          .withCredentials(credentialsProvider)
                                          .withRegion(region)
                                          .build();
    }

    @Provides
    @Singleton
    @Named("dbMapper")
    private DynamoDBMapper getDynamoDBMapper(AmazonDynamoDB dynamoDBClient) {

        return new DynamoDBMapper(dynamoDBClient);
    }
...... more providers using  dbMapper

现在,在我想使用此模块的地方,我想提供一些使用默认凭证提供程序的 AmazonDynamoDB 的不同实现。

public class MyModule extends AbstractModule {

    @Override
    protected void configure() {
        bind(AmazonDynamoDB.class).toProvider(AmazonDynamoDBClientProvider.class).in(Singleton.class);
        install(new LibraryModule());
    }

AmazonDynamoDBClientProvider 类 -

public class AmazonDynamoDBClientProvider implements Provider<AmazonDynamoDB> {

    private final String region;

    @Inject
    public AmazonDynamoDBClientProvider(@Named("aws.region") String region) {
        this.region = region;
    }

    @Override
    public AmazonDynamoDB get() {
        return AmazonDynamoDBClientBuilder.standard()
                                          .withRegion(region)
                                          .build();
    }
}

但是当我尝试这样做时,它在尝试创建 AmazonDynamoDB 时在库提供程序中失败,方法是说 A binding to com.amazonaws.services.dynamodbv2.AmazonDynamoDB was already configured

我想知道是否可以省略已经绑定(bind)在父模块中的类的提供者?如果可以,我们该怎么做?我找不到解决此问题的方法。

最佳答案

如果您可以更改 LibraryModule,那么您应该赋予它灵 active ,以绑定(bind)其默认实现或您提供的实现:

class LibraryModule extends AbstractModule {

  // Default implementation based on the code you've shown in LibraryModule
  static class DefaultDynamoDBProvider implements Provider<AmazonDynamoDB> {
    private final AWSCredentialsProvider credentialsProvider;
    private final String region;

    @Inject DefaultDynamoDBProvider(
        @Named("dbCredentials") AWSCredentialsProvider credentialsProvider,
        @Named("aws.region") String region) {
      this.credentialsProvider = credentialsProvider;
      this.region = region;
    }
    @Override AmazonDynamoDB get() {
      return AmazonDynamoDBClientBuilder
          .standard()
          .withCredentials(credentialsProvider)
          .withRegion(region)
          .build();
    }    
  }

  private Class<Provider<AmazonDynamoDB>> dynamoDbProviderClass;

  // if constructed with this constructor, uses default provider
  LibraryModule() {
    this(DefaultDynamoDBProvider.class);
  }

  // here, uses the supplied one. Builder pattern would be better
  LibraryModule(Class<Provider<AmazonDynamoDB>> providerClass) {
    this.dynamoDbProviderClass = providerClass;
  }

  protected void configure() {
    bind(AmazonDynamoDB.class)
        .toProvider(dynamoDbProviderClass)
        .in(Singleton.class);
  }
}

如果无法触摸 LibraryModule,请查看 Overriding Binding in Guice ,同时记住覆盖绑定(bind)是一种反模式,应该不惜一切代价避免:

  • Modules.override javadoc 说“更喜欢编写可以重用和测试而无需覆盖的较小模块”,并提供了与单元测试有关的示例

  • Guice 绑定(bind)很难追踪,但至少可以保证一旦找到绑定(bind),它就是正确的。 Modules.override() 使这项任务更加复杂。

  • 模块应该相互独立。在我们的场景中,某人可能已经安装了 LibraryModule 和连接到 Dynamo 的连接器,但是一旦他也安装了 OrderProcessingModule(假设您正在写的是这个),他的连接就断开了.现在他没有办法:要么是 Dynamo 要么是订单处理,或者是另一个更复杂的覆盖

关于java - 防止覆盖 guice 中已经绑定(bind)的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57662434/

相关文章:

wcf - 带 wcf 的 Autofac

python - Python 能否在不依赖服务定位器的情况下无缝地进行 DI?

java - 如何使用 google guice 将两个类绑定(bind)到一个类中?

gwt - 使用 Gin/Guice 注入(inject)实例

java - Java 控制台应用程序中的 Guice 自定义范围进入和退出

java - 使用 Twitter4j 转发并发表评论

java - 自动缩放的 Android 2x2 行图像

java - 我想在 Tapestry 页面中发布包含酒店的列表,但此错误反复出现

asp.net - 仅当接口(interface)尚未绑定(bind)时,如何在 Ninject 中绑定(bind)接口(interface)?

java - 使用 GWT 在 Eclipse Luna 中找不到 "New Web Application Project"选项