我最近在Throttler
类中添加了一个Server
字段,该字段仅在启用节流(这是一个配置项)时实例化,如果是,则每秒的最大请求数(另一个配置项)为传递给它的构造函数。
这是没有Throttler
依赖注入的代码:
public class Server {
private Config config;
private Throttler throttler;
@Inject
public Server(Config config) {
this.config = config;
if (config.isThrottlingEnabled()) {
int maxServerRequestsPerSec = config.getMaxServerRequestsPerSec();
throttler = new Throttler(maxServerRequestsPerSec);
}
}
}
public class Throttler {
private int maxRequestsPerSec;
public Throttler(int maxRequestsPerSec) {
this.maxRequestsPerSec = maxRequestsPerSec
}
}
现在要注入
Throttler
,我使用了Provider
,因为它不一定总是需要实例化。但是现在我被迫将Config
注入Throttler
并让其“自行配置”:public class Server {
private Config config;
private Provider<Throttler> throttlerProvider;
@Inject
public Server(Config config, Provider<Throttler> throttlerProvider) {
this.config = config;
this.throttlerProvider = throttlerProvider;
if (config.isThrottlingEnabled()) {
this.throttler = throttlerProvider.get();
}
}
}
public class Throttler {
private int maxRequestsPerSec;
@Inject
public Throttler(Config config) {
maxRequestsPerSec = config.getMaxServerRequestsPerSec();
}
}
我不喜欢这种解决方案,因为:
实用程序类(
Throttler
)对Config
有依赖性。现在,
Throttler
已绑定到特定的配置条目,这意味着除Server
之外,其他任何物品都不能使用它。我宁愿以某种方式将
maxRequestsPerSec
注入构造函数。Guice有可能吗?
最佳答案
Guice FAQ建议引入一个工厂接口,该接口使用其依赖项和客户端传递的其他参数来构建类。
public class Throttler {
...
public static class Factory {
@Inject
public class Factory(... Throttler dependencies ...) {...}
public Throttler create(int maxRequestsPerSec) {
return new Throttler(maxRequestsPerSec /*, injected Throttler dependencies */);
}
}
}
这样,Throtler的所有直接依赖项都封装在Throttler类中。
您也可以使用AssistedInject扩展名来减少样板代码。