如何实现“机器人腿"Google Guice 的用例? [英] How to implement the "robot legs" use case with Google Guice?
问题描述
我正在学习 Google Guice.你知道如何实现机器人腿"问题吗?让我用一个例子来解释这一点.
I'm learning Google Guice. Do you know how to implement the "robot legs" problem? Let me explain this with an example.
假设我有一个名为 Service
的类:
Let's say that I have some class called Service
:
@Singleton
public class Service {
@Inject
Source source;
}
接口Source
有两个实现:
public class SourceDatabase implements Source {
}
public class SourceFileSystem implements Source {
}
我的模块是这样实现的:
My module is implemented like this:
public class MyModule extends AbstractModule {
@Override
protected void configure() {
bind(Service.class).asEagerSingleton();
}
}
好吧,我想知道这是否可行:
Well, I would like to know if this is possible:
public class MainClass {
@Inject @SomeAnnotation("database")
Service serviceWithADatabaseSource;
@Inject @SomeAnnotation("file-system")
Service serviceWithAFileSystemSource;
}
确实存在一些让我这样做的注释或绑定,让我注释像 serviceWithADatabaseSource
这样的成员,这有助于 Guice 知道内部成员 source
应该是注入了 SourceDatabase
实现?
Does exist some annotation or binding that let me do that, let me annotate a member like serviceWithADatabaseSource
, and this helps Guice to know that the internal member source
should be injected with the SourceDatabase
implementation?
感谢 Daniel Martin 在他的评论中为我们提供此类问题的名称.
Thanks to Daniel Martin, for give us the name of this kind of problem on his comment.
推荐答案
As 记录在 Guice Wiki,您需要安装两个 PrivateModule s,每个都公开一个带有适合您的注释的服务.
As documented in the Guice Wiki, you need to install two PrivateModules, each of which exposes a Service with the right annotation for you.
public class MyModule extends AbstractModule {
@Override
protected void configure() {
install(new PrivateModule() {
@Override public void configure() {
// Bind Source to SourceDatabase.
bind(Source.class).to(SourceDatabase.class);
// Bind @Named("database") Service to Service.
bind(Service.class).annotatedWith(Names.named("database"))
.to(Service.class);
// Now expose @Named("database") Service without exposing
// either of the other two conflicting bindings.
expose(Service.class).annotatedWith(Names.named("database"));
}
});
install(new PrivateModule() {
@Override public void configure() {
// Same as above.
bind(Source.class).to(SourceFileSystem.class);
bind(Service.class).annotatedWith(Names.named("file-system"))
.to(Service.class);
expose(Service.class).annotatedWith(Names.named("file-system"));
}
});
}
}
如果模块不是 PrivateModule 实例,则这些到 Source 和 Service 的绑定会相互冲突.然而,相反,每个绑定都继承了来自注入器的所有公共绑定,但只向外界公开了 @Named(...) Service
.这样,相同的 Service
实现可以注入相同的未注释的 Source
,但返回不同的完全注入类型.
If the modules were not PrivateModule instances, those bindings to Source and Service would conflict with one another. However, instead, each binding inherits all the public bindings from the Injector but only exposes the @Named(...) Service
to the outside world. This way the same Service
implementation can inject the same non-annotated Source
but have it return different fully-injected types.
另请注意,您将无法在 PrivateModules 之外请求 Source
或 Service
(没有注释),因为您尚未建立绑定在任何非私有模块中.这应该是预料之中的:PrivateModule 绑定不应与任何公共绑定冲突,并且如果不通过 PrivateModule 的公开绑定之一进入,Guice 将不知道哪个 Source
或 Service
返回.
Also note that you will not be able to ask for a Source
or Service
(without an annotation) outside of the PrivateModules, because you haven't established a binding in any non-private Module. This should be expected: The PrivateModule bindings shouldn't conflict with any public bindings, and without entering through one of the PrivateModule's exposed bindings, Guice won't know which Source
or Service
to return.
最后,鉴于 Module 实例可以接受构造函数参数,将两个匿名内部 PrivateModules 提取到一个命名的等效项中可能是个好主意:
Finally, given that Module instances can take constructor parameters, it may be a good idea to extract the two anonymous inner PrivateModules into a named equivalent:
public class MyModule extends AbstractModule {
@Override
protected void configure() {
install(new SourcePrivateModule(SourceDatabase.class, "database"));
install(new SourcePrivateModule(SourceFileSystem.class, "file-system"));
}
}
这篇关于如何实现“机器人腿"Google Guice 的用例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!