我正在审查 Guice。假设我有以下设置:
public interface IsEmailer {...}
public interface IsSpellChecker {...}
public class Emailer implements IsEmailer {
@Inject
public class Emailer(final IsSpellChecker spellChecker)....
}
public class FrenchSpellChecker implements IsSpellChecker {....}
public class EnglishSpellChecker implements IsSpellChecker {....}
@BindingAnnotation public @interface English {}
@BindingAnnotation public @interface French {}
然后在我的模块中,我将接口(interface)绑定(bind)到它们各自的实现,并使用相应的绑定(bind)注释来注释拼写检查器。
现在,假设我需要基于运行时变量构建一个使用英语或法语拼写检查器的电子邮件程序。
我考虑在我的模块中使用命名提供程序:
@Provides
@English
IsEmailer provideEnglishEmailer() {
return new Emailer(new EnglishSpellChecker());
}
@Provides
@French
IsEmailer provideFrenchEmailer() {
return new Emailer(new FrenchSpellChecker());
}
它的工作原理如下:
IsEmailer emailer = myModule.getInstance(Key.get(IsEmailer.class,
French.class));
这是做这样的事情最干净的方法吗?毕竟,我被迫手动构造对象(在提供程序中)。
谢谢
最佳答案
首先一些注意事项:
通常您希望避免使用
getInstance
尽可能多,除了“根”元素(例如YourApplication
)。在 Guice 提供的任何服务中,您最好的选择是要求注入(inject)Provider<IsEmailer>
,或者@English Provider<IsEmailer>
和@French Provider<IsEmailer>
。 Guice 不会真正创建元素,直到您调用get
关于Provider
,因此创建Provider
的开销非常非常轻。您不必绑定(bind)到提供程序即可获取提供程序。 Guice 将解析
X
的任何绑定(bind),Provider<X>
,或@Provides X
任何注入(inject)X
或Provider<X>
自动且透明。Provider
实现可以采用注入(inject)的参数,就像@Provides
一样。方法。如果你想绑定(bind)很多东西到
@English
或@French
,您也可以调查private modules ,因为这听起来像 "robot legs"对我来说是个问题。
最简单的方法就是使用第一个项目符号并注入(inject) Provider
每个,特别是如果您只这样做一次。
如果你的运行时变量可以通过 Guice 访问,你也可以将它绑定(bind)在模块中。将其与 @Provides
一起放入您的模块中上面的注释。 (如前所述,您可能需要重写它们以分别接受 EnglishSpellChecker
和 FrenchSpellChecker
作为参数,以使拼写检查器能够注入(inject)自己的依赖项。)
@Provides IsEmailer provideEmailer(Settings settings,
@English Provider<IsEmailer> englishEmailer,
@French Provider<IsEmailer> frenchEmailer) {
if (settings.isEnglish()) {
return englishEmailer.get();
} else {
return frenchEmailer.get();
}
}
关于java - GUICE - 在运行时决定对象图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15214795/