Guice 指定用于注入的模块
Guice specify modules to use for injection
在我的应用程序中,有多个模块将某些内容绑定到特定名称或 class。有没有办法告诉 Guice,在解析要注入的依赖项时应该使用哪些模块。
我的简化依赖图看起来像这样,其中蓝色表示来自模块 1 的 classes,红色表示来自模块 2 的 classes。现在我想 创建两个实例来自 A class,但不同的 classes 绑定到某些依赖项.
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()
}
}
这就是 private modules 的问题所在。您仍然需要使用绑定注释来区分您是在请求 A
的 Impl1
版本还是 A
.
的 Impl2
版本
/** 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));
在我的应用程序中,有多个模块将某些内容绑定到特定名称或 class。有没有办法告诉 Guice,在解析要注入的依赖项时应该使用哪些模块。
我的简化依赖图看起来像这样,其中蓝色表示来自模块 1 的 classes,红色表示来自模块 2 的 classes。现在我想 创建两个实例来自 A class,但不同的 classes 绑定到某些依赖项.
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()
}
}
这就是 private modules 的问题所在。您仍然需要使用绑定注释来区分您是在请求 A
的 Impl1
版本还是 A
.
Impl2
版本
/** 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));