我想在Guice中实现与以下类似的东西:
public MyClass {
private final InjectedObject[] injectedObjects;
@Inject
public MyClass(InjectedObject[] injectedObjects) {
this.injectedObjects=injectedObjects;
}
}
即我希望能够创建一定数量的对象实例,并将它们作为数组注入另一个对象。我可能会这样做:
public MyClass {
private final InjectedObject[] injectedObjects;
@Inject
public MyClass(InjectedObjectProvider injectedObjectProvider) {
this.injectedObjects=injectedObjectProvider.getArrayOfInjectedObjects(5);
}
}
...但我想知道是否还有另一条更优雅的路线?
答案 0 :(得分:16)
不确定这是否符合您的需求,但当我需要注入多个相同类型的元素时,Multibindings为我工作(虽然它会生成一个集合)。
答案 1 :(得分:8)
我很好奇你为什么要热切地创造几个对象。您可能已成功注入Provider<InjectedObject>
,并在每次需要实例时调用Provider.get()
。如果你真的需要5,你可以在循环中构建它们:
public MyClass {
private final List<InjectedObject> injectedObjects;
@Inject
public MyClass(Provider<InjectedObject> injectedObjectProvider) {
injectedObjects = new ArrayList<InjectedObject>();
for (int i = 0; i < 5; i++) {
injectedObjects.add(injectedObjectProvider.get());
}
}
}
答案 2 :(得分:8)
一种选择是向你的班级注入Provider<InjectedObject>
,正如杰西所说:
public class MyClass {
private final List<InjectedObject> injectedObjects;
@Inject
public MyClass(Provider<InjectedObject> injectedObjectProvider) {
List<InjectedObject> objects = new ArrayList<InjectedObject>();
for (int i = 0; i < 5; i++) {
objects.add(injectedObjectProvider.get());
}
injectedObjects = Collections.unmodifiableList(objects);
}
}
这样做可能会有问题。如果InjectedObject
的范围限定为@Singleton
或@RequestScoped
,则每次调用injectedObjectProvider.get()
时都会得到相同的引用。注入Provider
来执行此操作的另一个问题是,API不清楚MyClass
依赖于InjectedObject的多个实例。最后,你在MyClass
中硬编码,需要注入五个实例。
您很少需要将Provider
注入对象。通常当我这样做时,这是因为当前对象的范围意味着它将比从属对象的范围更长寿(例如,需要访问@Singleton
对象的@RequestScoped
)。
您可以在构造函数中注入Provider
,而不是注入List<InjectedObject>
,并在Guice模块中创建一个提供者方法:
@Provides
MyClass prividesMyClass(Provider<InjectedObject> injectedObjectProvider) {
List<InjectedObject> objects = new ArrayList<InjectedObject>();
for (int i = 0; i < 5; i++) {
objects.add(injectedObjectProvider.get());
}
return new MyClass(objects);
}
(当然,您可以使用TypeLiteral
)
为什么这样更好?即使您仍然在此代码中对五个对象进行硬编码,但它在MyClass
中没有硬编码,因此MyClass
的客户端(包括MyClass
本身的测试)可以选择以不同的方式构建对象。
如果在Guice模块中对这些知识进行硬编码并不是一个好主意,您可以创建一个具有比Provider
更具体的合同的接口
public interface InjectedObjectRepository {
List<InjectedObject> getInjectedObjects();
}
即使您决定要让MyClass
负责知道要创建多少个实例,您也可能需要创建一个接口(可能名为InjectedObjectSupplier
,以便您可以明确记录您期望的每次都有独特的实例。
答案 3 :(得分:1)
添加此答案,以便人们知道如何注入数组,因为这首先出现在谷歌搜索上。我相信其中任何一个都可行:
在模块的配置中:
bind(InjectedObject[].class).toInstance(someArray);
或作为提供者方法:
@Provides
InjectedObject[] getInjectedObject(@Inject Provider<InjectedObject> provider) {
InjectedObject[] objects = new InjectedObject[5];
for (int i = 0; i < objects.length; i++) {
objects[i] = provider.get();
}
}