我正在使用Guice进行依赖注入,并希望创建一个如下所示的对象图:
d1 d2 / \ / \ b1 c1 b2 c2 \ / \ / a1 a2
所以我想创建A类的两个实例,每个实例都有这个结构。 用例可以是D是由两个客户端B和C使用的某种数据对象(例如,DB连接),它们都在servlet A中使用。
最小Java类定义:
public class A {
@Inject A(B b, C c) {}
}
public class B {
@Inject B(D d) {}
}
public class C {
@Inject C(D d) {}
}
public class D {}
现在我可以创建两个A:
的实例Injector injector = Guice.createInjector(new DiamondModule());
A a1 = injector.getInstance(A.class);
A a2 = injector.getInstance(A.class);
但是,如果我这样做,我会得到四个不同的D实例,这不是我想要的。请注意,声明D单例将无济于事,因为那时我将只获得单个D实例。
我已经看到了以下问题,但是那个问题的答案在这里不起作用,或者至少我不知道如何:Guice inject single instance into multiple objects without using @Singleton
有谁知道如何解决这个问题?或者这个设计有点不对劲?或者这已经是我必须申报自己范围的实例?
与此同时,我注意到这个问题与Dependency injection: Scoping by region (Guice, Spring, Whatever)重复,基于该问题的答案,我想出了一个解决方案。
基本思想是为每个钻石实例创建一个新的注入器,如下所示:
public class MainModule extends AbstractModule {
@Override
protected void configure() {
}
@Provides
A createA() {
return Guice.createInjector().getInstance(A.class);
}
}
现在将D设为单例,其范围限定为特定的注入器。
// class D is a singleton
@Singleton
public class D {}
答案 0 :(得分:2)
这被称为"机器人腿"问题(创建具有稍微不同实例的类似图表)并处理here。
class LegModule extends PrivateModule {
private final Class<? extends Annotation> annotation;
LegModule(Class<? extends Annotation> annotation) {
this.annotation = annotation;
}
@Override protected void configure() {
bind(Leg.class).annotatedWith(annotation).to(Leg.class);
expose(Leg.class).annotatedWith(annotation);
bindFoot();
}
abstract void bindFoot();
}
public static void main(String[] args) {
Injector injector = Guice.createInjector(
new LegModule(Left.class) {
@Override void bindFoot() {
bind(Foot.class).toInstance(new Foot("leftie"));
}
},
new LegModule(Right.class) {
@Override void bindFoot() {
bind(Foot.class).toInstance(new Foot("righty"));
}
});
}