java - 实例化每个范围/组的单例 - 陷入 Guice 依赖 hell

标签 java dependency-injection guice multiple-inheritance

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

主要问题是这个。我有一个在 API 的不同部分公开的 InterfaceAInterfaceB。有两个类实现了这两个接口(interface),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 的相同实例绑定(bind)到 InterfaceAInterfaceB 的所有注入(inject);所以,就像单例模式一样,除了:
  2. 单例仅针对特定范围或子注入(inject)器,其中许多是在程序执行期间创建的。

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

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

    No scope is bound to name.package.WhateverScope.
    

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

所有这些问题似乎是由于我需要能够配置是在父级中使用 TestClass 还是 RealClass ,但随后能够稍后将它们实例化为一个特定的对象组。我正在为如何完成这项工作而绞尽脑汁!

顺便说一句,Guice 作用域的文档非常糟糕,几乎无法理解。 This article是唯一让我到任何地方的人:

最佳答案

对于发布后不到一个小时的一些突破,我们深表歉意。

我似乎已经能够通过稍微滥用 http://code.google.com/p/google-guice/wiki/CustomScopes 提供的线程局部作用域实现来解决这个问题.在不使用子注入(inject)器的情况下,这似乎是解决此问题的一种比较干净的方法。不过,我不确定它是否“合适”。我仍然会接受其他答案。

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

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

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

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

我可能还有一些其他的可作用域对象,我希望它们在每个作用域内是不同的,所以我也绑定(bind)了它们。它们是上面的 TestClassRealClass。可能还有用 @ExperimentScoped 注释的 SomeScopedClass:

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

bind(SomeInterface.class).to(SomeScopedClass.class);

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

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.
}

在我的例子中,我可以完全放弃范围,因为我不关心在正确连接后跟踪范围中的对象集。但是,如果我稍后想回到这个范围并注入(inject)更多对象,它可能不会起作用。

希望这对某人有所帮助。 Guice 范围文档很糟糕!

关于java - 实例化每个范围/组的单例 - 陷入 Guice 依赖 hell ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15101191/

相关文章:

java - Guice - 如何提供一个 API,支持灵活的可插拔策略实现及其自己的绑定(bind)?

java - 如何为单个方法设置show_sql Hibernate参数?

java - 将 2D 数组网格中的 "path"存储到列表中

java - 使用 `jsonPath` 过滤掉包含空数组的元素的表达式

c# - EF 的 DbContext 的单例范围

java - Google Guice 独立批处理中的 JSR-352

java - Netbeans、java、创建 jar

java - 如何使用 Spring 注入(inject)从 Web 应用程序启动守护进程

c# - 使用带有 Umbraco Controller 的简单注入(inject)器

hibernate - 使用持久引用保留对象时,使用JPA遇到数据库死锁