使用 Guice 创建相同 class 的多个实例
Create multiple instances of the same class with Guice
对不起,如果这是一个微不足道的问题,我是 Guice 的新手。
假设我有以下 class:
public class MyClass {
@Inject
public MyClass(final MyDependency myDependency) {
this.name = myDependency.getName();
}
public String getName() {
this.name;
}
}
然后我想去别的地方做:
public class SomeOtherClass {
public void test() {
MyClass instanceFoo = injector.getInstance(MyClass.class);
MyClass instanceBar = injector.getInstance(MyClass.class);
assertTrue("foo", instanceFoo.getName());
assertTrue("bar", instanceBar.getName());
}
}
我想要 "MyClass" 的两个实例,一个名称为 "foo",另一个名称为 "bar"(即它们每个都有不同的实例它的依赖性也是如此)。如何将这 2 个实例添加到我的注入器,以及如何使用 "injector.getInstance"?
检索它们中的每一个
我不想为每个可能的依赖项创建 "MyClass" 的子class。
谢谢!
如标题所示,您的问题有一个更简单的解决方案:如果您想要任意数量的 MyClass 或 MyDependency 实例,您可以注入 Provider<MyClass>
或 Provider<MyDependency>
。无论您实际上是否在模块中绑定了提供者,都是如此;对于图中可用的任何 T,Guice 实际上可以注入 T
或 Provider<T>
。 (分别对应 Injector.getInstance
和 Injector.getProvider
。)
与问题的 body 一样,有两部分:为同一个 Class
制作多个可注射 Key
,并按照您想要的方式设置实例具有不同的名称和注入的依赖项。
键和绑定注释
Guice 使用 Key
识别绑定,它是 fully-qualified class(如 MyClass
或 List<MyClass>
)与可选的 "binding annotation".这是一个注解,它本身用 BindingAnnotation
或 javax.inject.Qualifier
进行注解;您可以创建自己的,或使用内置的名为 @Named
的字符串(因此 @Named("foo")
不同于 @Named("bar")
)。
大多数时候,您可以不直接使用 Key:在您的 bind
调用中使用 annotatedWith
或将注释添加到 @Provides
方法上,并通过放置来请求它们构造函数参数或@Inject-annotated 字段上的注释。但是,您仍然可以通过使用 Key 上的静态方法手动创建 Key 来使用 getInstance
和 getProvider
。 (对于复杂的情况,请使用 TypeLiteral 或 Names.named
;有关详细信息,请参阅他们的文档。)
设置实例
既然你知道如何注入 @Named("foo") MyClass
或 @Foo MyClass
,你如何提供它们?根据您的需要,我会选择以下三个选项之一:绑定 toInstance
、使用 @Provides
方法或创建 "assisted injection" 工厂。
如果您的 MyClass 实例本身不需要注入,并且您不改变或操纵实例状态,您可以只准备根据需要命名的实例,然后 bind
它们toInstance
.
您还可以编写一个 @Provides @Named("foo") MyClass
方法,它接受一个 MyClass
参数(Guice 通过注入器提供),设置名称,然后 returns实例。这是编写 Provider class 或实例的 low-overhead 替代方法,将为您提供一个新的实例,而不是 toInstance
绑定所暗示的共享。
如果你真的想让 name
成为你的 class 构造函数参数的一部分,也许是为了保持实例不可变,你可以使用 "Assisted Injection" 告诉 Guice 哪些参数是你自己提供的,哪些来自 Guice 注入器。这将允许您注入 MyClass.Factory
并调用 myClassFactory.create("foo")
,您可以直接在您的消费 classes 中执行此操作,或使用上面的 @Provides
技术。细节有点超出问题的范围,但请查看 "Assisted Injection" 了解有关语法和添加适当 JAR 的详细信息。
对不起,如果这是一个微不足道的问题,我是 Guice 的新手。 假设我有以下 class:
public class MyClass {
@Inject
public MyClass(final MyDependency myDependency) {
this.name = myDependency.getName();
}
public String getName() {
this.name;
}
}
然后我想去别的地方做:
public class SomeOtherClass {
public void test() {
MyClass instanceFoo = injector.getInstance(MyClass.class);
MyClass instanceBar = injector.getInstance(MyClass.class);
assertTrue("foo", instanceFoo.getName());
assertTrue("bar", instanceBar.getName());
}
}
我想要 "MyClass" 的两个实例,一个名称为 "foo",另一个名称为 "bar"(即它们每个都有不同的实例它的依赖性也是如此)。如何将这 2 个实例添加到我的注入器,以及如何使用 "injector.getInstance"?
检索它们中的每一个我不想为每个可能的依赖项创建 "MyClass" 的子class。
谢谢!
如标题所示,您的问题有一个更简单的解决方案:如果您想要任意数量的 MyClass 或 MyDependency 实例,您可以注入 Provider<MyClass>
或 Provider<MyDependency>
。无论您实际上是否在模块中绑定了提供者,都是如此;对于图中可用的任何 T,Guice 实际上可以注入 T
或 Provider<T>
。 (分别对应 Injector.getInstance
和 Injector.getProvider
。)
与问题的 body 一样,有两部分:为同一个 Class
制作多个可注射 Key
,并按照您想要的方式设置实例具有不同的名称和注入的依赖项。
键和绑定注释
Guice 使用 Key
识别绑定,它是 fully-qualified class(如 MyClass
或 List<MyClass>
)与可选的 "binding annotation".这是一个注解,它本身用 BindingAnnotation
或 javax.inject.Qualifier
进行注解;您可以创建自己的,或使用内置的名为 @Named
的字符串(因此 @Named("foo")
不同于 @Named("bar")
)。
大多数时候,您可以不直接使用 Key:在您的 bind
调用中使用 annotatedWith
或将注释添加到 @Provides
方法上,并通过放置来请求它们构造函数参数或@Inject-annotated 字段上的注释。但是,您仍然可以通过使用 Key 上的静态方法手动创建 Key 来使用 getInstance
和 getProvider
。 (对于复杂的情况,请使用 TypeLiteral 或 Names.named
;有关详细信息,请参阅他们的文档。)
设置实例
既然你知道如何注入 @Named("foo") MyClass
或 @Foo MyClass
,你如何提供它们?根据您的需要,我会选择以下三个选项之一:绑定 toInstance
、使用 @Provides
方法或创建 "assisted injection" 工厂。
如果您的 MyClass 实例本身不需要注入,并且您不改变或操纵实例状态,您可以只准备根据需要命名的实例,然后
bind
它们toInstance
.您还可以编写一个
@Provides @Named("foo") MyClass
方法,它接受一个MyClass
参数(Guice 通过注入器提供),设置名称,然后 returns实例。这是编写 Provider class 或实例的 low-overhead 替代方法,将为您提供一个新的实例,而不是toInstance
绑定所暗示的共享。如果你真的想让
name
成为你的 class 构造函数参数的一部分,也许是为了保持实例不可变,你可以使用 "Assisted Injection" 告诉 Guice 哪些参数是你自己提供的,哪些来自 Guice 注入器。这将允许您注入MyClass.Factory
并调用myClassFactory.create("foo")
,您可以直接在您的消费 classes 中执行此操作,或使用上面的@Provides
技术。细节有点超出问题的范围,但请查看 "Assisted Injection" 了解有关语法和添加适当 JAR 的详细信息。