Frage

Ich möchte etwas ähnlich der folgenden in Guice erreichen:

public MyClass {

    private final InjectedObject[] injectedObjects;

    @Inject
    public MyClass(InjectedObject[] injectedObjects) {
        this.injectedObjects=injectedObjects;
    }
}

dh ich möchte in der Lage sein, eine bestimmte Anzahl von Instanzen eines Objekts zu erstellen, und injizieren sie in ein anderes Objekt als Array. Ich könnte wahrscheinlich das tun, statt:

public MyClass {

    private final InjectedObject[] injectedObjects;

    @Inject
    public MyClass(InjectedObjectProvider injectedObjectProvider) {
        this.injectedObjects=injectedObjectProvider.getArrayOfInjectedObjects(5);
    }
}

... aber ich frage mich, ob es einen anderen Weg war, das war elegantere?

War es hilfreich?

Lösung

Ich bin neugierig, warum Sie mehrere Objekte mit Spannung erstellt werden soll. Möglicherweise müssen Erfolg eine Provider<InjectedObject> Injektion und ruft jedes Provider.get() Mal, wenn Sie eine Instanz benötigen. Wenn Sie wirklich 5 benötigen, könnten Sie ‚em in einer Schleife bauen:

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

Andere Tipps

Nicht sicher, ob dies Ihren Bedürfnissen entspricht, aber Multibindings arbeitete ich, wenn ich brauchte mehrere Elemente der gleichen Art zu injizieren (es erzeugt einen Satz obwohl).

Eine Möglichkeit wäre, eine Provider<InjectedObject> in Ihre Klasse zu injizieren, wie Jesse erwähnt:

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

Das Tun kann problematisch sein. Wenn InjectedObject als @Singleton oder @RequestScoped scoped, dann jedes Mal, rufen Sie injectedObjectProvider.get() Sie die gleiche Referenz erhalten würde. Ein weiteres Problem bei Injektion eines Provider dies zu tun, ist es nicht klar wäre, von der API, die MyClass auf mehrere Instanzen von InjectedObject abhängt. Schließlich haben Sie in MyClass fest einprogrammiert, die es mit fünf Fällen injiziert werden muss.

Es ist selten, dass Sie eine Provider in ein Objekt injizieren müssen. Normalerweise, wenn ich dies tun, ist es, weil der Umfang des aktuellen Objekts bedeutet, dass es langlebiger ist als der Umfang des abhängigen Objekts (zum Beispiel ein @Singleton, der den Zugriff auf ein @RequestScoped Objekt benötigt).

Statt einen Provider die Injektion Sie eine List<InjectedObject> in den Konstruktor injizieren kann, und eine Provider-Methode in einem Guice Modul erstellen:

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

(Sie könnten natürlich, binden eine TypeLiteral verwenden)

Warum ist das besser? Auch wenn Sie noch hart codierte fünf Objekte in diesem Code werden, ist es nicht hart codiert in MyClass, damit Kunden von MyClass (einschließlich der Tests für MyClass selbst) wählen kann das Objekt auf unterschiedliche Weise zu konstruieren.

Wenn Hartcodierung dieses Wissens in einem Guice Modul keine gute Idee ist, können Sie stattdessen eine Schnittstelle erstellen, die einen bestimmten Vertrag als Provider hat

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

Auch wenn Sie entscheiden, dass Sie MyClass zu wissen, verantwortlich sein wollen, wie viele Instanzen zu erstellen, möchten Sie vielleicht eine Schnittstelle (vielleicht namens InjectedObjectSupplier erstellen, damit Sie ausdrücklich, dass Sie jedes Mal erwarten eine einzigartige Instanz dokumentieren könnte.

Das Hinzufügen dieser Antwort so, dass die Menschen wissen, wie ein Array zu injizieren, da diese zuerst auf einer Google-Suche kommen. Ich glaube, entweder von diesen funktioniert:

In einem configure des Moduls: bind(InjectedObject[].class).toInstance(someArray); oder als Provider-Methode:

@Provides
InjectedObject[] getInjectedObject(@Inject Provider<InjectedObject> provider) {
  InjectedObject[] objects = new InjectedObject[5];
  for (int i = 0; i < objects.length; i++) {
    objects[i] = provider.get();
  }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top