Java 实例化每个作用域/组的单例-卡在Guice依赖关系地狱中

Java 实例化每个作用域/组的单例-卡在Guice依赖关系地狱中,java,dependency-injection,guice,multiple-inheritance,Java,Dependency Injection,Guice,Multiple Inheritance,这个问题是我试图实现的的延续,我还尝试了其他方法来解决这个问题,但到目前为止没有任何效果 主要问题是这个。我有一个InterfaceA和InterfaceB,它们暴露在API的不同部分。有两个类实现了这两个接口,TestClass和RealClass,因此根据我是在测试还是在做其他事情,我可以执行以下操作: bind(InterfaceA.class).to(TestClass.class); bind(InterfaceB.class).to(TestClass.class); 或者,对于

这个问题是我试图实现的的延续,我还尝试了其他方法来解决这个问题,但到目前为止没有任何效果

主要问题是这个。我有一个
InterfaceA
InterfaceB
,它们暴露在API的不同部分。有两个类实现了这两个接口,
TestClass
RealClass
,因此根据我是在测试还是在做其他事情,我可以执行以下操作:

bind(InterfaceA.class).to(TestClass.class);
bind(InterfaceB.class).to(TestClass.class); 
或者,对于生产:

bind(InterfaceA.class).to(RealClass.class);
bind(InterfaceB.class).to(RealClass.class);
我对使用这些类有两个要求:

  • 我需要将
    TestClass
    RealClass
    的相同实例绑定到
    InterfaceA
    InterfaceB
    的所有注入;所以,就像一个单例模式,除了:
  • 单例仅适用于特定的作用域或子注入器,其中许多是在程序执行期间创建的
  • 默认的无作用域方法导致为每个接口注入创建多个
    RealClass
    /
    TestClass
    实例。我不想这样,所以我试着用作用域、子注入器和其他方法实现它。没有任何效果:

    • :我创建了一个新的注入器,并尝试将
      TestClass
      RealClass
      绑定到该注入器中的单例实例。问题是,是否正在使用
      TestClass
      RealClass
      是在父注入器中配置的,并且(除非处于
      开发阶段
      )。例如,无法在父注入器中将
      InterfaceA
      绑定到
      TestClass
      ,然后在子注入器中将其作为单例重新绑定
    • 范围方法:并注释
      TestClass
      RealClass
      。然后,我进入并退出这个作用域以获取该作用域中的单个实例。问题是,我的代码是多线程的,如果从一个线程更改范围,会影响全局注入器可以看到的内容,并会妨碍创建其他实例
    • 儿童注射器和内窥镜的组合方法。我尝试为这个自定义作用域的每次使用创建一个子注入器,但是在父类中绑定
      RealClass
      失败

      No scope is bound to name.package.WhateverScope.
      
      因为它似乎坚持认为,
      WhateverScope
      始终可用,而不仅仅是在儿童注射器中

    所有这些问题似乎都是由于这样一个事实:我需要能够配置是否在父对象中使用
    TestClass
    RealClass
    ,但随后能够将它们作为一个单独的对象组实例化。我正在为如何完成这件事而发愁


    顺便说一下,Guice范围的文档非常可怕,几乎不可能理解。是唯一一个能让我有所收获的人:

    为发帖后不到一个小时出现的突破性进展道歉

    我似乎已经能够通过某种程度上滥用在提供的线程本地作用域实现来解决这个问题。这似乎是一个有点干净的方法来解决这个问题,而不使用儿童注射器。不过,我不确定这是否“合适”。我仍然会接受其他答案

    这就是我所做的。首先,我创建范围的一个实例,将其绑定到适当的注释,并使其在注入器中可用:

    ThreadLocalScope scope = new ThreadLocalScope();
    bindScope(ExperimentScoped.class, scope);
    bind(ThreadLocalScope.class).toInstance(scope);
    
    ThreadLocalScope scope = injector.getInstance(ThreadLocalScope.class);      
    scope.enter();
    
    try {
        // Seed the seed-able keys
        scope.seed(SomeKey.class, keyInstance);
        scope.seed(SomeOtherKey.class, otherKeyInstance);    
    
        SomeScopedClass instance = injector.getInstance(SomeScopedClass.class);
    
        // Hooray! instance was injected with the seeds and created just for this scope!
    }
    finally {
        scope.exit(); // Throws away the scope and referenced objects.
    }
    
    然后,正如文档所述,我需要为范围中的每种类型的密钥绑定一个假提供程序:

    bind(SomeKey.class)
      .toProvider(ThreadLocalScope.<SomeKey>seededKeyProvider())
      .in(ExperimentScoped.class);
    bind(SomeOtherKey.class)
      .toProvider(ThreadLocalScope.<SomeOtherKey>seededKeyProvider())
      .in(ExperimentScoped.class);
    
    最后,我可以使用作用域从不同线程并行地创建不同的相互依赖对象集。即使使用相同的喷油器,每个螺纹也可以执行以下操作:

    ThreadLocalScope scope = new ThreadLocalScope();
    bindScope(ExperimentScoped.class, scope);
    bind(ThreadLocalScope.class).toInstance(scope);
    
    ThreadLocalScope scope = injector.getInstance(ThreadLocalScope.class);      
    scope.enter();
    
    try {
        // Seed the seed-able keys
        scope.seed(SomeKey.class, keyInstance);
        scope.seed(SomeOtherKey.class, otherKeyInstance);    
    
        SomeScopedClass instance = injector.getInstance(SomeScopedClass.class);
    
        // Hooray! instance was injected with the seeds and created just for this scope!
    }
    finally {
        scope.exit(); // Throws away the scope and referenced objects.
    }
    
    在我的例子中,我可以完全放弃作用域,因为我不在乎在正确连接后跟踪作用域中的对象集。但如果我想稍后再回到这个范围并注入更多的对象,它可能不会起作用

    希望这对别人有帮助。Guice作用域文档太糟糕了