我正在尝试学习 Guice,但以下场景似乎很难。假设我有 A、B 和 C 类。我应该能够执行以下操作(请注意,此示例对实际情况有所简化):
- A是全局单例
- A 依赖于 ProviderB(即工厂)
- B 依赖于 A 和 ProviderC(即工厂)
- C 依赖于 A 和 B
当B创建C时,C的依赖B必须是同一个实例,即从C的角度来看,B是单例。
我试过创建子注入(inject)器:
private static class MainModule extends AbstractModule{
@Override
protected void configure() {
bind(A.class).in(Singleton.class);
}
@Provides
B createB(Injector injector){
return injector.createChildInjector(new SubModule()).getInstance(B.class);
}
}
private static class SubModule extends AbstractModule{
@Override
protected void configure() {
bind(B.class).in(Singleton.class);
bind(C.class);
}
}
public static void main(String[] args) {
Injector injector = Guice.createInjector(new MainModule());
A a = injector.getInstance(A.class);
B b1 = a.getB();
B b2 = a.getB();
// all following C's are different instances
C b1c1 = b1.getC(); //this has b1 and a
C b1c2 = b1.getC(); //this has b1 and a
C b2c1 = b2.getC(); //this has b2 and a
C b2c2 = b2.getC(); //this has b2 and a
但是随后 Guice 给出了 B 已经绑定(bind)的错误(MainModule 中的 Provides 方法)。因此我需要重写 MainModule 的 B 绑定(bind),但这似乎无法使用子注入(inject)器。
这个问题可以通过使用多个注入(inject)器来解决,例如为 createB 方法创建一个新的并将 A 作为参数注入(inject),但似乎使用多个注入(inject)器不是最佳实践。
编辑:向 C 实例添加注释以阐明它们应该拥有哪个 B 实例
最佳答案
我会将其作为答案发布,它更像是解决方法而不是完整的解决方案,但对于我的应用程序来说可能已经足够好了:
private static class MainModule extends AbstractModule{
@Override
protected void configure() {
bind(A.class).in(Singleton.class);
bind(SubModule.class).in(Singleton.class);
}
@Provides
B createB(Injector injector){
SubModule m = injector.getInstance(SubModule.class);
return Guice.createInjector(m).getInstance(B.class);
}
}
private static class SubModule extends AbstractModule{
private final A a;
@Inject
public SubModule(A a) {
this.a = a;
}
@Override
protected void configure() {
bind(A.class).toInstance(a);
bind(B.class).in(Singleton.class);
bind(C.class);
}
}
首先,我认为大多数绑定(bind)都将在 MainModule 中,但我想如果它们仅在 B 的上下文中使用(并像我对 A 所做的那样路由其他人),无论如何都可以将它们移动到 SubModule。这主要类似于链接问题的答案: Dependency injection: Scoping by region (Guice, Spring, Whatever)但是我创建了新的顶级注入(inject)器,因为我似乎无法在两个模块中绑定(bind) B,否则我可能会在这里遗漏一些东西..
(第一次这样做,不确定这是否是发布解决方法作为自己的答案的正确方法)
关于java - Guice 和 "scoped"单例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28827911/