这个问题是 Using guice for a framework with injected classes, proper way to initialize?的延续,我已经尝试实现,也尝试了其他方法来解决这个问题,但到目前为止没有任何效果。
主要问题是这个。我有一个在 API 的不同部分公开的 InterfaceA
和 InterfaceB
。有两个类实现了这两个接口(interface),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
的相同实例绑定(bind)到InterfaceA
和InterfaceB
的所有注入(inject);所以,就像单例模式一样,除了: - 单例仅针对特定范围或子注入(inject)器,其中许多是在程序执行期间创建的。
默认的无范围方法会导致为每个接口(interface)注入(inject)创建多个 RealClass
/TestClass
实例。我不想这样,所以我尝试使用作用域、子注入(inject)器和其他方法来实现它。没有任何效果:
- Child injector approach :我创建了一个新的注入(inject)器并尝试将
TestClass
或RealClass
绑定(bind)到该注入(inject)器中的单例实例。问题是,是否正在使用TestClass
或RealClass
在父注入(inject)器中配置,并且 since it's a singleton, it's already instantiated (除非在Stage.DEVELOPMENT
中)。例如,无法在父注入(inject)器中将InterfaceA
绑定(bind)到TestClass
,然后在子注入(inject)器中将其重新绑定(bind)为单例。 - 范围方法:I create a custom scope并注释
TestClass
和RealClass
。然后,我进入和退出该范围以获取该范围内的单个实例。问题是我的代码是多线程的,并且从一个线程更改范围会影响全局注入(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)了它们。它们是上面的 TestClass
和 RealClass
。可能还有用 @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/