Чтобы повторить Правильный ответ Колина , Assisted Injection - это путь, и Guice предлагает Assisted Injection (через отдельную зависимость / JAR) с 2.0. Вы можете прочитать больше о реализации Guice на странице Guiki wiki AssistedInject , но у меня не было бы ничего примера, кроме того, что написал Колин.
Одна альтернатива, которую вы можете рассмотреть, находится в AutoFactory , которая генерирует кодовые реализации для вас. (Это часть Google Auto, набора генераторов кода для Java, который создает реализации аннотаций, сервисы, объекты с неизменяемыми значениями и фабрики.) Это де-факто стандарт для Dagger, но он применим к любой среде JSR-330, включая Guice.
Относительно вашего вопроса № 1, я отклонюсь от Колина и скажу, что то, что вы ищете, по сути своей несколько опасно: если @Singleton
объекты существуют на протяжении всего жизненного цикла вашего приложения, но ваша фабрика WidgetA принимает контейнер, тогда ваш WidgetA может существовать до того, как ваш контейнер будет готов, или он будет существовать после уничтожения вашего контейнера.
Если ваш контейнер WidgetA также @Singleton
, то вы можете создать WidgetA без фабрики, и все идет хорошо: вы можете пропустить фабрику, связать контейнер, нормально связать WidgetA и ввести Provider<WidgetA>
(доступно без дополнительная настройка), чтобы отложить создание WidgetA, пока вы не будете готовы.
Если ваш реальный запрос заключается в том, чтобы WidgetA существовал ровно столько, сколько существует Контейнер, но для того, чтобы WidgetA / B / C все использовали один и тот же Контейнер и WidgetA для этого времени, вы можете считать дочерним инжектором где вы связываете свой контейнер и виджеты. Таким образом, каждый Контейнер получает свой собственный WidgetA, каждая инъекция WidgetA является последовательной в этом контейнере, и вы избавляетесь от WidgetA, когда получаете новый Контейнер. Конечно, если ваш Контейнер становится доступным только после того, как ваш Инжектор работает, и после этого он остается постоянным, вы можете использовать этот дочерний инжектор в качестве основного инжектора и после этого запустить WidgetA.
Если ваш WidgetA зависит от контейнера, который не запускается как доступный, будьте осторожны: это может быть «инъекция, расширяющая область действия», потому что ваш контейнер будет жить как @Singleton
в WidgetA, даже если он иначе быть мусором В лучшем случае это может быть утечка памяти и странные ошибки, когда в вашем приложении существует несколько Контейнеров. Вы можете использовать модуль с состоянием, как вы использовали, но в любом случае будьте очень осторожны.