Guice指定用于注射的模块

时间:2016-08-26 08:13:39

标签: java dependency-injection guice

在我的应用程序中,有多个模块将某些内容绑定到特定的名称或类。有没有办法告诉Guice,在解析依赖注入时应该使用哪些模块。

我的简化依赖图看起来像这样,其中blue表示来自模块1的类,red表示来自模块2的类。现在我想从A类创建两个实例,但是不同的类绑定到某些依赖项< /强>

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 个答案:

答案 0 :(得分:1)

这是为private modules构建的问题。您仍然需要使用绑定注释来区分您是要求Impl1A还是Impl2A

/** 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));