2017-03-08 57 views
3

我使用的吉斯依赖注入,并希望创建一个对象图,看起来像这样:创建在吉斯钻石对象图(不辛格尔顿)

 
    d1  d2 
/\ /\ 
b1 c1 b2 c2 
    \/ \/
    a1  a2 
  • A1和A2表示A类的实例等
  • 类A依赖于类B和C
  • 类B和C各自取决于d类
  • 然而,在B和C中使用d的实例应该是相同的

所以我想创建两个实例的A类,每个都有这个结构。 用例可被D为某种数据对象(也就是说,一个DB连接),用于由两个客户端B和C,这两者都在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 {} 

现在我可以创建的两个实例:

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)副本,并根据anwers到这个问题,我想出了一个解决方案。

基本的想法是创建一个新的注射器对钻石的每个实例,就像这样:

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

的可能的复制[依赖注入:通过区域范围设定(吉斯,春天,无论)](http://stackoverflow.com/questions/3014140/dependency-injection-scoping-by-region-guice-spring -whatever) – olenz

回答

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")); 
     } 
     }); 
} 
+0

这是一个不错的解决方案,如果我想拥有钻石的两个实例,甚至可以在每个实例中进行专门的变体。 但是,我一直在寻找的是一个解决方案,它允许我创建x版本的钻石。 – olenz