Внедрение зависимости - что, если время жизни зависимости меньше, чем зависимый объект? - PullRequest
3 голосов
/ 27 января 2011

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

Вот почему: Что происходиткогда зависимый объект имеет более длительный срок службы, чем зависимости, в которые он был введен?

Пример приложения: У меня есть класс BusinessLogic, который создается для всего срока службы моего приложения.Для этого класса требуется объект DataContext для выполнения операций с базой данных.Ранее я создал реферат DataContextFactory с двумя реализациями: StaticDataContextFactory и WebDataContextFactory.Первый поддерживает один DataContext для всего жизненного цикла приложения, тогда как второй будет создавать новые DataContexts для каждого HTTP-запроса.

Проблема в примере: Как видите, все будетхорошо, когда используется StaticDataContextFactory.Однако, когда используется WebDataContextFactory, BusinessLogic завершится неудачей, поскольку он вводится с DataContext, срок действия которого истекает / удаляется после завершения первого запроса.

Мой вопрос: Должны ли все зависимые объекты иметь время жизни, которое меньше или равно времени жизни его зависимостей?Если так, то что происходит, когда время жизни каждой зависимости неизвестно коду, который создает экземпляры зависимых классов?

Ответы [ 4 ]

1 голос
/ 28 января 2011

Как отмечали другие авторы, для этого существуют решения на основе прокси.Однако я бы отнес это к категории «последнее средство».

Вы можете выполнить рефакторинг, чтобы устранить это несоответствие, и я думаю, что в конечном итоге будет удобнее работать с конечным результатом.Я не знаю много о вашем сценарии, но несколько вещей, которые вы могли бы рассмотреть:

  1. Избавьтесь от фабрик, позвольте контейнеру ввести DataContext и затем используйте контейнеруправление временем жизни для настройки времени жизни DataContext в разных средах

  2. Не делайте компонент BusinessLogic единичным экземпляром.Если вы создаете новый для каждого использования, он, естественно, выберет веб-область DataContext, если DC настроен таким образом, или один DC в другой конфигурации

  3. ЕслиBusinessLogic имеет состояние или является дорогостоящим для создания экземпляров, перемещения дорогостоящих / находящихся в состоянии деталей в подкомпоненты, имеющие срок службы в одном экземпляре

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

Успешная работа сВремя жизни в IoC действительно в значительной степени зависит от поддержания четкого разделения между единицами работы, что в веб-среде приятно и естественно - если вам удастся, вам придется поторопиться с потоком.1028 *

1 голос
/ 27 января 2011

Веб-интеграция Spring Framework решает эту проблему, используя прокси и аспекты. Более длинные объекты вводятся с прокси для более коротких объектов. Каждый прокси-сервер знает, как извлечь «текущую» версию своего делегата с более короткой областью действия через сеанс HTTP или HTTP-запрос (для bean-объектов, определяемых сессией и запросом соответственно).

См. http://static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-factory-scopes-other-injection

0 голосов
/ 27 января 2011

Почему вы не можете запросить XXXDataContextFactory для «Текущего» DataContext?Ваша статическая фабрика всегда будет возвращать одну и ту же, а ваша веб-фабрика будет возвращать одну на основе текущего запроса HttpRequest.

0 голосов
/ 27 января 2011

Я размышлял над подобным вопросом.(Проверьте мой пост на DI: Контейнер внедрения зависимостей , Второй ответ) Я понял, что правильная реализация, использующая интерфейсное внедрение, действительно сработает.

Причина, по которой я думаю, что это может работать хорошопоскольку извлечение интерфейса из объекта является обычным делом, при условии, что иерархии интерфейса спроектированы должным образом, даже если объекты выходят за пределы области действия, данные, относящиеся к интерфейсу, будут фактически сохраняться.Поэтому у вас не будет зависимости, выходящей за рамки видимости, до того, как код, который его использует, освободит ваш фактический объект.

В примере, который я показал, я развернул свой собственный "DI", хотяна самом деле это не настоящий паттерн DI, я считаю, что он отлично справляется со своей работой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...