2017-03-08 56 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