Una opción sería la de inyectar un Provider<InjectedObject>
en su clase, como se ha mencionado Jesse:
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);
}
}
Hacer esto puede ser problemático . Si InjectedObject
tiene un ámbito de @Singleton
o @RequestScoped
, cada vez que llame al injectedObjectProvider.get()
obtendrá la misma referencia. Otro problema con la inyección de un Provider
para hacer esto es que no sería claro desde la API que MyClass
depende de varias instancias de InjectedObject. Finalmente, ha codificado en MyClass
que debe inyectarse con cinco instancias.
Es raro que necesite inyectar un Provider
en un objeto. Usualmente cuando hago esto, es porque el alcance del objeto actual significa que tendrá una vida más larga que el alcance del objeto dependiente (por ejemplo, un @Singleton
que necesita acceso a un objeto @RequestScoped
).
En lugar de la inyección de un Provider
, se puede inyectar un List<InjectedObject>
en el constructor, y crear un método proveedor en un módulo de 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);
}
(que podría, por supuesto, se unen mediante un TypeLiteral
)
¿Por qué es esto mejor? Aunque todavía está codificando cinco objetos en este código, no está codificado en MyClass
, por lo que los clientes de MyClass
(incluidas las pruebas para MyClass
en sí) pueden elegir construir el objeto de diferentes maneras.
Si la codificación dura de este conocimiento en un módulo de Guice no es una buena idea, en su lugar puede crear una interfaz que tiene un contrato más específico que Provider
public interface InjectedObjectRepository {
List<InjectedObject> getInjectedObjects();
}
Incluso si usted decide que quiere MyClass
para ser responsable de saber cuántas instancias crear, es posible que desee crear una interfaz (quizás llamada InjectedObjectSupplier
para poder documentar explícitamente que espera una instancia única cada vez.
Gracias por la sugerencia - la razón de tener varias proporcionan impaciencia es ser capaz de colocar en un ThreadPool: el número de instancias en el grupo dependerá de la cantidad de núcleos disponibles. – Rich
¿Cómo harías esto si no tuvieras el control del código fuente de MyClass, pero solo deseas inyectarlo usando enlaces y otro código en la configuración del Módulo (preferiblemente sin usar Multibindings ya que no es compatible con Gin)? – Snekse
Snekse, podría crear un método @Provides que tome el proveedor como parámetro y llame al constructor MyClass al final. –