Один из вариантов - добавить 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
, чтобы вы могли явно задокументировать, что каждый раз вы ожидаете уникальный экземпляр) .