Guice和“范围”单身人士

时间:2015-03-03 09:12:19

标签: java dependency-injection guice

我正在尝试学习Guice,但以下情况似乎很难。假设我有A,B和C类。我应该能够执行以下操作(请注意,此示例稍微简化了实际情况):

  1. A是全球单身人士
  2. A依赖于ProviderB(即工厂)
  3. B依赖于A和ProviderC(即工厂)
  4. C依赖于A和B
  5. 当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实例

1 个答案:

答案 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,或者我可能会错过这里的某些内容..

(第一次这样做,不确定这是否是以自己的答案发布解决办法的正确方法)