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
方法来访问它;您可以注入 Foo
或 Provider<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
}
我正在使用 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
方法来访问它;您可以注入 Foo
或 Provider<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
}