我希望在Guice中实现类似以下的功能:
public MyClass {
private final InjectedObject[] injectedObjects;
@Inject
public MyClass(InjectedObject[] injectedObjects) {
this.injectedObjects=injectedObjects;
}
}
Run Code Online (Sandbox Code Playgroud)
即我希望能够创建一定数量的对象实例,并将它们作为数组注入另一个对象.我可能会这样做:
public MyClass {
private final InjectedObject[] injectedObjects;
@Inject
public MyClass(InjectedObjectProvider injectedObjectProvider) {
this.injectedObjects=injectedObjectProvider.getArrayOfInjectedObjects(5);
}
}
Run Code Online (Sandbox Code Playgroud)
...但我想知道是否还有另一条更优雅的路线?
我很好奇你为什么要急切地创建几个对象.您可能已成功注入一个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());
}
}
}
Run Code Online (Sandbox Code Playgroud)
一种选择是在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);
}
}
Run Code Online (Sandbox Code Playgroud)
这样做可能会有问题.如果InjectedObject作为@Singleton或作为范围@RequestScoped,那么每次打电话给injectedObjectProvider.get()你都会获得相同的参考.注入a Provider来执行此操作的另一个问题是,从API中MyClass依赖于InjectedObject的多个实例并不清楚.最后,你已经硬编码MyClass,需要注入五个实例.
您很少需要将a Provider注入对象.通常当我这样做时,这是因为当前对象的范围意味着它将比从属对象的范围更长寿(例如,@Singleton需要访问@RequestScoped对象的范围).
Provider您可以将一个List<InjectedObject>注入到构造函数中,而不是注入一个,并在Guice模块中创建一个provider方法:
@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);
}
Run Code Online (Sandbox Code Playgroud)
(你当然可以使用a绑定TypeLiteral)
为什么这样更好?即使您仍在对此代码中的五个对象进行硬编码,但它并未进行硬编码MyClass,因此MyClass(包括MyClass自身测试)的客户端可以选择以不同方式构造对象.
如果在Guice模块中对这些知识进行硬编码并不是一个好主意,那么您可以创建一个具有更具体合同的接口. Provider
public interface InjectedObjectRepository {
List<InjectedObject> getInjectedObjects();
}
Run Code Online (Sandbox Code Playgroud)
即使您决定要MyClass负责了解要创建的实例数,也可能需要创建一个接口(可能已命名,InjectedObjectSupplier因此您可以明确地记录您希望每次都有一个唯一的实例.
| 归档时间: |
|
| 查看次数: |
7664 次 |
| 最近记录: |