13

我想在 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);
    }
}

...但我想知道是否还有其他更优雅的路线?

4

4 回答 4

16

不确定这是否适合您的需求,但是当我需要注入多个相同类型的元素时, Multibindings对我有用(尽管它会产生一个集合)。

于 2009-12-18T02:04:24.970 回答
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());
    }
  }
}
于 2009-02-27T01:48:17.477 回答
8

正如 Jesse 提到的,一种选择是将 aProvider<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作用域为@Singletonor @RequestScoped,那么每次调用injectedObjectProvider.get()时都会得到相同的引用。注入 a 来执行此操作的另一个问题是,从依赖于多个 InjectedObject 实例Provider的 API 中不清楚。MyClass最后,您已经硬编码,MyClass因为它需要注入五个实例。

您很少需要将 aProvider注入对象。通常当我这样做时,这是因为当前对象的范围意味着它将比依赖对象的范围更长寿(例如,@Singleton需要访问@RequestScoped对象的 a )。

Provider您可以将 aList<InjectedObject>注入构造函数,并在 Guice 模块中创建提供程序方法,而不是注入 a :

@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);
}

(当然,您可以使用 a 绑定TypeLiteral

为什么这样更好?尽管您仍然在此代码中硬编码五个对象,但它并没有硬编码在 中MyClass,因此MyClass(包括MyClass自身的测试)的客户端可以选择以不同的方式构造对象。

如果在 Guice 模块中硬编码这些知识不是一个好主意,您可以改为创建一个具有比Provider

public interface InjectedObjectRepository {
  List<InjectedObject> getInjectedObjects();
}

即使您决定要MyClass负责知道要创建多少个实例,您也可能希望创建一个接口(也许命名InjectedObjectSupplier以便您可以明确记录您每次都期望一个唯一的实例。

于 2009-04-24T21:25:49.130 回答
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();
  }
}
于 2012-04-17T22:25:32.283 回答