2016-08-26 7 views
1

私のアプリケーションには、特定の名前またはクラスに何かをバインドする複数のモジュールがあります。 Guiceに指示する方法はありますか。どのモジュールを使用して注入する依存関係を解決するべきですか?Guiceは注入に使用するモジュールを指定します

青はモジュール1のクラスを示し、赤はモジュール2のクラスを示します。Aクラスから2つのインスタンスを作成しますが、異なるクラスはいくつかの依存関係にバインドされます

Dependencies

public class Module1 extends AbstractModule { 
    @Override 
    protected void configure() { 
     bind(C.class).to(C_Impl1.class) 
     bind(D.class).to(D_Impl1.class) 
    } 
} 


public class Module2 extends AbstractModule { 
    @Override 
    protected void configure() { 
     bind(C.class).to(C_Impl2.class) 
     bind(D.class).to(D_Impl2.class) 
    } 
} 

public class Application { 
    @Inject @UseModules(Module1, ...) private final A someClassUsingImpl1; 
    @Inject @UseModules(Module2, ...) private final A someClassUsingImpl2; 

    public void doSomethingWithImpl1() { 
     someClassUsingImpl1.doSomething() 
    } 

    public void doSomethingWithImpl2() { 
     someClassUsingImpl2.doSomething() 
    } 
} 

答えて

1

これがために建てられたprivate modules問題です。バインディングアノテーションを使用してAImpl1バージョンか、AImpl2バージョンを要求するかどうかを区別する必要があります。

/** Marks Impl1 classes. Inject @Impl1 A to get A using C_Impl1 and D_Impl1. */ 
@BindingAnnotation 
@Retention(RetentionPolicy.RUNTIME) 
@interface Impl1 {} 

/** Marks Impl2 classes. Inject @Impl2 A to get A using C_Impl2 and D_Impl2. */ 
@BindingAnnotation 
@Retention(RetentionPolicy.RUNTIME) 
@interface Impl2 {} 

/** This is now a PrivateModule. Only exposed bindings can be used outside. */ 
public class Module1 extends PrivateModule { 
    @Override 
    protected void configure() { 
     // Bind C and D as you had before. 
     bind(C.class).to(C_Impl1.class); 
     bind(D.class).to(D_Impl1.class); 
     // Here's the tricky part: You're binding "@Impl1 A" to 
     // "A" without a binding annotation, but only in here. 
     bind(A.class).annotatedWith(Impl1.class).to(A.class); 
     // Now you expose @Impl1 A, so it can be used outside. 
     // As long as A, C, and D are only bound within private modules, 
     // they won't conflict with one another, and @Impl1 A is unique. 
     expose(A.class).annotatedWith(Impl1.class); 
    } 
} 

/** Treat Module2 the same way, as a private module. */ 

public class Application { 
    @Inject @Impl1 private final A someClassUsingImpl1; 
    @Inject @Impl2 private final A someClassUsingImpl2; 
    // ... 
} 

これはあなたのための一般的なパターンである場合は、コンストラクタのパラメータとして変化のクラスになりますので、あなた自身を繰り返す必要はありません一般的なPrivateModuleを作成します。これらはトップレベルのインジェクタまたはinstalled within other modulesに追加できます。

Injector injector = Guice.createInjector(new YourMainModule(), 
    new ImplModule(Impl1.class, C_Impl1.class, D_Impl1.class), 
    new ImplModule(Impl2.class, C_Impl2.class, D_Impl2.class)); 
関連する問題