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

时间:2016-03-29 16:34:49

标签: java guice

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

@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 A{
   @Inject private RetryServiceCaller retryServiceCaller;
}

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

我一直在研究FactoryModuleBuilder来使用它并为这个类创建一个工厂。但由于该类具有配置文件中的参数,因此无法找到使其工作的方法。

像这样的东西

  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

2 个答案:

答案 0 :(得分:1)

你的第一种方法应该可以正常工作。如果您不希望RetryServiceCaller成为单例,请从提供程序方法中删除@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了解更多示例。

答案 1 :(得分:1)

Guice可以自动提供零参数工厂:您可以始终注入Foo,而不是注入Provider<Foo>。这使您可以随时随地致电fooProvider.get()创建实例。您不必绑定到Provider或使用Provides方法来访问此内容;您可以注入FooProvider<Foo>是否使用bind(...).to(...)类型绑定,toProvider绑定,toInstance绑定,@Provides方法,或其他任何内容,Guice会致电get或自动返回内部Provider

(返回的提供商也会尊重范围,因此您需要删除@Singleton范围才能获得多个实例,并注意toInstance绑定将总是返回相同的实例。)

这不是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"));
}

在你的班上:

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

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