Guice FactoryModuleBuilder 一个带有构造函数参数的实例

Guice FactoryModuleBuilder an instance with constructor parameters

我正在使用 Guice 初始化一个 class 以及配置文件中的一些参数

@Provides
@Singleton
RetryServiceCaller provideMaxRetryAttempts(@Named("config") JsonObject config) throws IOException {
    JsonObject retryDetails = config.getJsonObject("retry_details");
    return new RetryServiceCaller(retryDetails.getInteger("maxRetryAttempts"), retryDetails.getInteger("upperBoundary"), retryDetails.getInteger("lowerBoundary"),
                                  retryDetails.getLong("multiplicationFactor"), retryDetails.getInteger("timeout"), retryDetails.getInteger("increaseTimeout"));
}

这个 class 被注入到另一个也是单例的 class 中。

class A{
   @Inject private RetryServiceCaller retryServiceCaller;
}

但现在的问题是,由于这个新的 class A 是单例,所以每次有人使用这个 class A 时,我都需要克隆 retryServiceCaller。

我一直在研究 FactoryModuleBuilder 以使用它并为此创建一个工厂 class。但是由于 class 有来自配置文件的参数,我找不到让它工作的方法。

像这样

  class A{
       @Inject private RetryServiceCaller.Factory retryServiceCallerFactory;

   }

然后在我的 RetryServiceCaller 中实现这个

public interface Factory {
    @Inject
    RetryServiceCaller create();
}


@Inject
public RetryServiceCaller(int maxRetryAttempts, int upperBoundary, int lowerBoundary, long multiplicationFactor, int timeout, int incrementTimeout) {
    this.maxRetryAttempts = maxRetryAttempts;
    this.upperBoundary = upperBoundary;
    this.lowerBoundary = lowerBoundary;
    this.multiplicationFactor = multiplicationFactor;
    this.timeout = timeout;
    this.incrementTimeout = incrementTimeout;
}

但是 guice 向我抛出错误说

No implementation for com.proxy.handlers.RetryServiceCaller$Factory was bound

您的第一种方法应该可以正常工作。如果你不希望 RetryServiceCaller 是一个单例,从 provider 方法中删除 @Singleton 注释,并且将为每个注入点创建一个新实例。

辅助注射也可以在这里工作,但它太过分了。如果你想走那条路:

interface RetryServiceCallerFactory {
  RetryServiceCaller create(String configParam1, String configParam2);
}

public class RetryServiceCaller {
  @AssistedInject
  public RetryServiceCaller(String configParam1, String configParam2) {}
}

然后,在你的模块中

install(new FactoryModuleBuilder().build(Factory.class);

并在您的注入点中

@Inject RetryServiceCallerFactory factory;

RetryServiceCaller create(JsonObject config) {
  return factory.create(config.getFirstParam(), config.getSecondParam());
}

您可以参考 documentation 以获得更广泛的示例。

Guice 可以自动提供一个零参数工厂:您可以随时注入 Provider<Foo> 而不是注入 Foo。这使您可以随时随地调用 fooProvider.get() 来创建一个实例。您不必绑定到 Provider 或使用 Provides 方法来访问它;您可以注入 FooProvider<Foo>,无论您使用 bind(...).to(...) 类型绑定、toProvider 绑定、toInstance 绑定、@Provides 方法,或其他任何东西,Guice 将自动调用 get 或 return 内部 Provider

(returned Provider 也会考虑作用域,因此您需要删除 @Singleton 作用域才能获得多个实例,并注意 toInstance 绑定将 总是 return 相同的实例。)

这不是 FactoryModuleBuilder 的工作;仅当您需要 在同一类型中混合注入和非注入构造函数参数时才使用 FactoryModuleBuilder.

您完成的绑定应如下所示:

@Provides
/* NOT @Singleton */
RetryServiceCaller provideMaxRetryAttempts(@Named("config") JsonObject config) throws IOException {
    JsonObject retryDetails = config.getJsonObject("retry_details");
    return new RetryServiceCaller(retryDetails.getInteger("maxRetryAttempts"), retryDetails.getInteger("upperBoundary"), retryDetails.getInteger("lowerBoundary"),
                                  retryDetails.getLong("multiplicationFactor"), retryDetails.getInteger("timeout"), retryDetails.getInteger("increaseTimeout"));
}

在你的class中:

@Inject public YourCallerConsumer(Provider<RetryServiceCaller> callerProvider) {
  this.callerProvider = callerProvider;
}

public void doAction() {
  RetryServiceCaller newCaller = callerProvider.get();
  // interact with caller
}