我正在尝试学习Guice,但以下情况似乎很难。假设我有A,B和C类。我应该能够执行以下操作(请注意,此示例稍微简化了实际情况):
当B创建C时,C的依赖关系B必须是同一个实例,即从C的角度来看,B是单例。
我尝试过创建儿童注射器:
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已经绑定的错误(MainModule中的Provide方法)。因此,我需要覆盖MainModule的B绑定,但这似乎不可能使用子注入器。
通过使用多个注射器可解决该问题,例如:为createB方法创建一个新的并注入A作为参数,但似乎使用多个注入器并不是最佳实践。
编辑:为C实例添加了注释,以阐明他们应该具有哪个B实例
答案 0 :(得分:1)
我会将此作为答案发布,它更像是解决方法而非完整解决方案,但对我的应用程序来说可能还是足够好:
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);
}
}
首先,我认为大多数绑定都在MainModule中,但我猜他们无论如何都可以移动到SubModule,如果它们仅用在B的上下文中(并且像我用A做的那样路由其他人)。这与链接问题的答案大致相似: Dependency injection: Scoping by region (Guice, Spring, Whatever)但我创建了新的顶级注入器,因为它似乎无法在两个模块中绑定B,或者我可能会错过这里的某些内容..
(第一次这样做,不确定这是否是以自己的答案发布解决办法的正确方法)