【问题标题】:Instantiating per-scope/group singletons - stuck in Guice dependency hell实例化每个范围/组的单例 - 陷入 Guice 依赖地狱
【发布时间】:2013-02-26 23:04:06
【问题描述】:

这个问题是 Using guice for a framework with injected classes, proper way to initialize? 的延续,我已经尝试实施,也尝试了其他方法来解决这个问题,但到目前为止没有任何效果。

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

bind(InterfaceA.class).to(TestClass.class);
bind(InterfaceB.class).to(TestClass.class); 

或者,用于生产:

bind(InterfaceA.class).to(RealClass.class);
bind(InterfaceB.class).to(RealClass.class);

我对使用这些类有两个要求:

  1. 我需要TestClassRealClass 的相同实例绑定到InterfaceAInterfaceB 的所有注入;所以,就像一个单例模式,除了:
  2. 单例仅适用于特定范围或子注入器,其中许多是在程序执行期间创建的。

默认的无范围方法会导致为每个接口注入创建多个 RealClass/TestClass 实例。我不希望这样,所以我尝试使用范围、子注入器和其他方法来实现它。没有任何效果:

  • Child injector approach:我创建了一个新的注入器并尝试将 TestClassRealClass 绑定到该注入器中的单例实例。问题是,在父注入器中配置了TestClass 还是RealClass,而since it's a singleton, it's already instantiated(除非在Stage.DEVELOPMENT 中)。例如,无法在父注入器中将 InterfaceA 绑定到 TestClass,然后在子注入器中将其重新绑定为单例。
  • 范围方法:I create a custom scope 并注解TestClassRealClass。然后,我进入和退出此范围以获取该范围内的单个实例。问题是我的代码是多线程的,并且从一个线程更改范围会影响全局注入器可以看到的内容,并且会影响创建其他实例。
  • 结合子注入器和范围方法。我尝试为每次使用此自定义范围创建一个子注入器,但随后在父级中绑定 RealClass 失败并出现

    No scope is bound to name.package.WhateverScope.
    

    因为它似乎坚持WhateverScope 始终可用,而不仅仅是在子注射器中。

所有这些问题似乎是由于我需要能够配置是否在父级中使用TestClassRealClass,但随后能够以单例的形式实例化它们一组特定的对象。我正在为如何完成这项工作而烦恼!

顺便说一句,Guice 范围的文档很糟糕,几乎无法理解。 This article 是唯一一个让我走到任何地方的人:

【问题讨论】:

    标签: java dependency-injection guice multiple-inheritance


    【解决方案1】:

    对于发布后不到一个小时的一些突破表示歉意。

    我似乎能够通过滥用http://code.google.com/p/google-guice/wiki/CustomScopes 提供的线程本地范围实现来解决此问题。在不使用儿童注射器的情况下,这似乎是一种解决此问题的干净方法。不过,我不确定它是否“正确”。我仍然会接受其他答案。

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

    ThreadLocalScope scope = new ThreadLocalScope();
    bindScope(ExperimentScoped.class, scope);
    bind(ThreadLocalScope.class).toInstance(scope);
    

    然后,正如文档所述,我需要为将在范围内播种的每种类型的密钥绑定一个虚假提供程序:

    bind(SomeKey.class)
      .toProvider(ThreadLocalScope.<SomeKey>seededKeyProvider())
      .in(ExperimentScoped.class);
    bind(SomeOtherKey.class)
      .toProvider(ThreadLocalScope.<SomeOtherKey>seededKeyProvider())
      .in(ExperimentScoped.class);
    

    我还可能有一些其他可作用域的对象,我希望在每个作用域内都与众不同,所以我也绑定了这些对象。这些是上面的TestClassRealClass。可能还有SomeScopedClass@ExperimentScoped注解:

    bind(InterfaceA.class).to(TestClass.class).in(ExperimentScoped.class);
    bind(InterfaceB.class).to(TestClass.class).in(ExperimentScoped.class);
    
    bind(SomeInterface.class).to(SomeScopedClass.class);
    

    最后,我可以使用作用域从不同的线程并行创建不同的相互依赖对象集。每个线程都可以执行以下操作,即使它们使用相同的注入器:

    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 范围界定文档很糟糕!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-23
      • 2015-12-06
      相关资源
      最近更新 更多