我最近在Throttler
类中添加了Server
字段,只有在启用了限制(这是配置条目)时才会实例化,如果是,则每个请求的最大数量sec(另一个配置项)将传递给它的构造函数。
以下是没有依赖注入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可以吗?
答案 0 :(得分:2)
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 */);
}
}
}
这样,Throttler的所有直接依赖关系都保留在Throttler类中。
您还可以使用AssistedInject扩展名来减少样板代码。
答案 1 :(得分:0)
这完全取决于您如何实现Provider接口和应用程序。如果获取maxRequestsPerSec的唯一方法是来自Config,您可以按照以下方式执行操作:
您可以注入特定的Provider实现,并在其中设置一个setter。因此,在构造函数中,您注入CustomProvider<Throttler>
(实现Provider
),然后执行setMaxRequestsPerSec
,然后在实例化Throttler时在get
方法中使用它。
如果你不想注射CustomProvider
,你可以注入提供者,然后进行instanceof
检查,但我认为注入CustomProvider会更好。