Управление жизненным циклом с помощью Google Guice

Есть ли рекомендуемый шаблон для выключения/закрытия объектов, созданных с помощью Guice?

Жизненный цикл, к которому я стремлюсь:

  1. Подготовьте модуль Guice
  2. Создать инжектор
  3. Используйте инжектор через свой код для получения объектов (injector.getInstance(Foo.class))
  4. ...
  5. Закройте все ресурсы, удерживаемые указанными объектами (дескрипторы файлов, TCP-соединения и т. д.). Я хочу, чтобы это был детерминированный шаг (а не «когда-нибудь, когда запустится GC»).

person ripper234    schedule 04.11.2009    source источник
comment
Возможно, вы захотите добавить пример кода к своему вопросу, потому что я действительно не понимаю, что вы имеете в виду.   -  person dlinsin    schedule 04.11.2009
comment
Добавил еще некоторые детали.   -  person ripper234    schedule 04.11.2009
comment
Используйте инжектор через свой код для получения объектов (injector.getInstance(Foo.class)) - это определенно не то, как предполагается использовать Guice или любой DI. Это просто сервис-локатор. Он должен строить ваш граф объектов, а инжектор должен быть создан и указан только в каком-то корневом классе загрузчика.   -  person ColinD    schedule 04.11.2009
comment
Он должен создаваться только в загрузчике, но любой объект может использовать его для получения доступа к другим объектам. Желательно, чтобы он просто зависел от нужных ему объектов и вводил их автоматически, но это не всегда так. В любом случае, это не относится к моему вопросу.   -  person ripper234    schedule 04.11.2009
comment
Да, именно поэтому я прокомментировал, а не ответил. Я думаю, что в любом месте, где вы захотите использовать инжектор.getInstance(Foo.class), вы должны иметь возможность внедрить Provider‹Foo› и использовать его вместо этого.   -  person ColinD    schedule 04.11.2009
comment
Какая разница? Возможно, мне следует начать с другого вопроса, но почему внедрение Provider лучше, чем внедрение Injector? Я думаю, одна из причин заключается в том, чтобы разрешить не использовать инжектор в модульных тестах... но это означает, что если классу нужно создать несколько объектов, ему нужны все их поставщики, а одного инжектора достаточно.   -  person ripper234    schedule 04.11.2009
comment
Но тогда класс ясно объявляет, от чего он зависит, тогда как, когда вы видите класс, который имеет ссылку на инжектор, вы понятия не имеете, что он может оттуда получить. И да, это довольно большая разница для модульного тестирования ... не нужно настраивать инжектор, просто создайте поддельный провайдер, который возвращает экземпляры так, как вы этого хотите. Вы больше не зависите от механизма предоставления зависимостей... только от самих зависимостей.   -  person ColinD    schedule 04.11.2009
comment
+1 КолинД. Кстати: если вы хотите обрабатывать транзакции, попробуйте сохранить деформацию: code.google.com/p/warp -persist ... можно указать единицу работы. может быть, это то, что вы можете использовать?   -  person Karussell    schedule 04.02.2010
comment
Эти комментарии - пустая трата времени! Отличный вопрос!   -  person rektide    schedule 18.03.2013


Ответы (1)


Я хочу, чтобы это был детерминированный шаг (а не «когда-нибудь, когда запустится GC»).

Извините, но тогда Java вам не подходит. Инфраструктура DI не знает, когда все ссылки на объект исчезли. Это знает только ГК.

Если у вас есть «закрываемый» ресурс, используйте шаблон try/finally, чтобы закрыть его (см. ниже).

Closable c = // ...
try {
   c.use();
} finally {
   c.close();
}

Теперь, чтобы вернуться вразнос немного. Guice может знать, когда область действия начинается и заканчивается. Ваша настраиваемая область может запустить этап очистки, когда он завершится. Эта область может даже возвращать прокси, поэтому объекты будут недействительными, если вы попытаетесь получить к ним доступ за пределами разрешенной области.

(Ну и +1 ColinD - провайдеры инжектов. :)

РЕДАКТИРОВАНИЕ: Guiceyfruit имеет некоторую поддержку Жизненные циклы

person Michael Lloyd Lee mlk    schedule 05.11.2009
comment
Я думаю, что это просто классическое непонимание того, для чего нужен GC (особенно легко сделать эту ошибку, если вы программировали на C++). В языке со сборкой мусора время жизни объекта/GC не имеет ничего общего с высвобождением ресурсов, таких как дескрипторы файлов или сетевые сокеты. - person Simon Howard; 05.11.2009
comment
Блок кода не выделяет объект, поэтому он не несет ответственности за его освобождение. В частности, синглтоны (внутри модуля Guice) получаются с помощью Injector.getInstance(), но их не следует закрывать после использования. - person ripper234; 05.11.2009
comment
Весь этот вопрос во многом зависит от того, что именно вы делаете и в каком контексте. У разных объектов разные жизненные циклы, разные области видимости и т. д., поэтому универсального простого решения не существует. Вы делаете это в веб-приложении? Вы в основном говорите о закрытии синглетонов при выключении? - person ColinD; 05.11.2009
comment
Синглтоны могут быть выпущены только во время закрытия приложения (то есть через хук выключения). Я уверен, что вы могли бы написать область, которая справится с этим. - person Michael Lloyd Lee mlk; 05.11.2009
comment
Кроме того, если блок кода извлекает объект без области действия от поставщика и использует его, он определенно будет нести ответственность за закрытие этого объекта в случае необходимости, несмотря на то, что сам не создает его. - person ColinD; 05.11.2009
comment
Блок кода не выделяет объект — объект создается через провайдера (или внедренный инжектор) или внедряется в этот объект. Если это предусмотрено, я бы сказал, что класс, который запросил его, несет ответственность за его выпуск. - person Michael Lloyd Lee mlk; 05.11.2009
comment
@mlk, относительно вашего утверждения: Структура DI не знает, когда все ссылки на объект исчезли. Это знает только сборщик мусора. Верно, но структура DI содержит ссылку на одноэлементные экземпляры, провайдеров и модули! И должен быть какой-то способ инициировать выпуск всех этих вещей из DI, сказать инжектору и модулям отказаться от них. Например, в RestEasy я реализовал следующее: 843 . Когда контекст сервлета уничтожается, он вызывает аннотированные методы JSR250 PreDestroy для модулей, чтобы вручную запустить очистку. - person rektide; 19.03.2013
comment
Я согласен, что вы можете сделать это с элементами с четко определенными областями (как в случае с Guicetfruit, ссылка на который приведена выше). Именно об этом и было все «Теперь немного отступить». - person Michael Lloyd Lee mlk; 19.03.2013