我的Java代码使用接口的多个实现(下例中的BugTemplate),其中绑定的实现依赖于上下文。
在Guice中,我认为实现这一目标的正确方法是使用BindingAnnotations。但是,我的用例与规范示例不同,因为上下文是从接口的实现中删除的一个级别。
总结可能的依赖关系:
FooBugFinder - > BugFiler - > FooBugTemplate
BarBugFinder - > BugFiler - > BarBugTemplate
等
示例代码:
class FooBugFinder {
// ...
public findBugsAndFileThem() {
List<Bug> bugs = findBugs();
bugFiler.fileBugs(bugs);
}
@Inject
FooBugFinder(BugFiler bugFiler) {
// BugFiler should have been instantiated with a FooBugTemplate.
this.bugFiler = bugFiler;
}
}
class BugFiler {
// ...
public fileBugs(List<Bug> bugs) {
List<FormattedBugReport> bugReports = bugTemplate.formatBugs(bugs);
fileBugReports(bugReports);
}
@Inject
BugFiler(BugTemplate bugTemplate) {
// The specific implementation of BugTemplate is context-dependent.
this.bugTemplate = bugTemplate;
}
}
interface BugTemplate {
List<FormattedBugReport> formatBugs(List<Bug> bugs);
}
class FooBugTemplate implements BugTemplate {
@Overrides
List<FormattedBugReport> formatBugs(List<Bug> bugs) {
// ...
}
}
我的第一个想法是对ctor进行如下注释:
FooBugFinder(@Foo BugFiler bugFiler) { }
但是,Guice如何知道在向BugFiler的构造函数注入参数时应用该注释?
换句话说,FooBugFinder需要一个用FooBugTemplate实例化的BugFiler实例。 BarBugFinder需要一个BugFiler实例,该实例使用BarBugTemplate实例化。
有什么想法吗?
答案 0 :(得分:1)
您可以通过创建公开带注释的BugFiler
对象的私有模块来实现此目的:
abstract class BugFilerModule extends PrivateModule {
private final Class<? extends Annotation> annotation;
BugFilerModule(Class<? extends Annotation> annotation) {
this.annotation = annotation;
}
@Override protected void configure() {
bind(BugFiler.class).annotatedWith(annotation).to(BugFiler.class);
expose(BugFiler.class).annotatedWith(annotation);
bindBugTemplate();
}
abstract void bindBugTemplate();
}
然后,当您创建注射器时:
Injector injector = Guice.createInjector(
new BugFilerModule(Foo.class) {
@Override void bindBugTemplate() {
bind(BugTemplate.class).to(FooBugTemplate.class);
}
},
new BugFilerModule(Bar.class) {
@Override void bindBugTemplate() {
bind(BugTemplate.class).to(BarBugTemplate.class);
}
},
/* other modules */);
您可以按照建议的方式创建FooBugFinder
:
public class FooBugFinder {
@Inject
public FooBugFinder(@Foo BugFiler fooBugFiler) {
...
}
}