我有以下课程:
public class CacheModule extends AbstractModule {
@Override
protected void configure() {
bindConstant().annotatedWith(Names.named(TIMEOUT")).to(60);
// ...etc.
}
}
public class DefaultCacheAdaptor implements CacheAdaptor {
private CacheModule bootstrapper = new CacheModule();
@Named("TIMEOUT") private int timeout;
// other fields omitted for brevity
public DefaultCacheAdaptor() {
super();
Injector injector = Guice.createInjector(bootstrapper);
@Named("TIMEOUT") int t = injector.getInstance(Integer.class);
setTimeout(t);
}
}
public class QueueModule extennds AbstractModule {
@Override
public void configure() {
bind(CacheAdaptor.class).to(DefaultCacheAdaptor.class);
}
}
public class DefaultQueueAdaptor implements QueueAdaptor {
private QueueModule bootstrapper = new QueueModule();
private CacheAdaptor cacheAdaptor;
public DefaultQueueAdaptor() {
super();
Injector injector = Guice.createInjector(bootstrapper);
setCacheAdaptor(injector.getInstance(CacheAdaptor.class));
}
}
CacheModule
/ CacheAdaptor
/ DefaultCacheAdaptor
位于与QueueModule
/ QueueAdaptor
/ DefaultQueueAdaptor
不同的JAR中,因此后者JAR在运行时依赖于前JAR(显然)。
以这种方式编码的目的是允许CacheModule
在用户写入时DefaultCacheAdaptor
下提升/注入整个对象图:
CacheAdaptor cacheAdaptor = new DefaultCacheAdaptor();
同样适用于QueueAdaptor
。
只有这样发生才会QueueAdaptor
注入CacheAdaptor
。
但是,DefaultCacheAdaptor
是其自有对象树的“根”,CacheModule
应始终注入。
所以我问:如何从DefaultCacheAdaptor
内部CacheAdaptor
绑定QueueModule
,但要确保DefaultCacheAdaptor
本身由CacheModule
初始化/引导{1}}?提前致谢!
答案 0 :(得分:1)
说实话,听起来这个问题实际上并不是Guice之一,而是整个软件工程中的标准问题:确保您的依赖关系做他们声称要做的事情。 QueueModule不应该关注DefaultCacheAdaptor是否符合其总契约。相反,为DefaultCacheAdaptor编写一个单元测试,保证它自己引导,然后在没有第二个想法的情况下在QueueModule中使用它。
这尤其正确,因为DefaultCacheAdaptor具有完全不相关的注入树。您应该能够不透明地使用DefaultCacheAdaptor,并停止关于QueueAdaptor及其实现细节。它的引导是其实现的一部分,而不是它的API。
即使您要将两个Injector图合并为一个(例如injecting the Injector并调用createChildInjector),但在编译时保证绑定您的方法很少因为Module
在运行时工作,所以在其他模块中需要存在。你最好的选择是编写单元测试。您可以通过调用requireBinding
来更快地失败,如果该特定依赖关系不会在外部得到满足,则会在Injector创建时失败。