Каковы преимущества контейнеров для инъекций зависимости? - PullRequest
102 голосов
/ 25 сентября 2008

Я понимаю преимущества самого внедрения зависимости. Давайте возьмем весну например. Я также понимаю преимущества других функций Spring, таких как AOP, помощники разных типов и т. Д. Мне просто интересно, каковы преимущества конфигурации XML, такие как:

<bean id="Mary" class="foo.bar.Female">
  <property name="age" value="23"/>
</bean>
<bean id="John" class="foo.bar.Male">
  <property name="girlfriend" ref="Mary"/>
</bean>

по сравнению с простым старым кодом Java, таким как:

Female mary = new Female();
mary.setAge(23);
Male john = new Male();
john.setGirlfriend(mary);

, который легче отлаживается, проверяется время компиляции и может быть понят любым, кто знает только Java. Итак, каково основное назначение инфраструктуры внедрения зависимостей? (или фрагмент кода, который показывает его преимущества.)


UPDATE:
В случае

IService myService;// ...
public void doSomething() {  
  myService.fetchData();
}

Как IoC Framework может угадать, какую реализацию myService я хочу внедрить, если их несколько? Если есть только одна реализация данного интерфейса, и я позволю контейнеру IoC автоматически решить использовать его, он будет нарушен после появления второй реализации. И если намеренно существует только одна возможная реализация интерфейса, вам не нужно внедрять его.

Было бы очень интересно увидеть небольшой фрагмент конфигурации для IoC, который демонстрирует его преимущества. Я давно пользуюсь Spring и не могу привести такой пример. И я могу показать отдельные строки, которые демонстрируют преимущества hibernate, dwr и других фреймворков, которые я использую.


ОБНОВЛЕНИЕ 2:
Я понимаю, что конфигурацию IoC можно изменить без перекомпиляции. Это действительно такая хорошая идея? Я могу понять, когда кто-то хочет изменить учетные данные БД без перекомпиляции - он может быть не разработчиком. Как часто в вашей практике кто-то, кроме разработчика, меняет конфигурацию IoC? Я думаю, что для разработчиков нет усилий перекомпилировать этот конкретный класс вместо изменения конфигурации. А для тех, кто не является разработчиком, вы, вероятно, захотите упростить его жизнь и предоставить более простой файл конфигурации.


ОБНОВЛЕНИЕ 3:

Внешняя конфигурация отображения между интерфейсами и их конкретными реализациями

Что такого хорошего в том, чтобы сделать его экстентальным? Вы не делаете весь свой код внешним, хотя вы определенно можете - просто поместите его в файл ClassName.java.txt, прочитайте и скомпилируйте вручную на лету - вы избежали перекомпиляции. Почему следует избегать компиляции?!

Вы экономите время кодирования, потому что вы предоставляете отображения декларативно, а не в процедурном коде

Я понимаю, что иногда декларативный подход экономит время. Например, я объявляю только один раз сопоставление между свойством bean-компонента и столбцом DB, и hibernate использует это отображение при загрузке, сохранении, построении SQL на основе HSQL и т. Д. Именно здесь работает декларативный подход. В случае Spring (в моем примере), объявление имеет больше строк и имеет ту же выразительность, что и соответствующий код. Если есть пример, когда такое объявление короче кода - я бы хотел его увидеть.

Принцип инверсии управления упрощает модульное тестирование, поскольку вы можете заменить реальные реализации поддельными (например, заменить базу данных SQL на оперативную)

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

mary = new FakeFemale();

Я понимаю преимущества DI. Я не понимаю, какие преимущества добавляет внешняя конфигурация XML по сравнению с настройкой кода, который делает то же самое. Я не думаю, что следует избегать компиляции - я компилирую каждый день, и я все еще жив. Я думаю, что конфигурация DI - плохой пример декларативного подхода. Декларация может быть полезна, если она объявляется один раз и используется много раз по-разному - например, hibernate cfg, где сопоставление между свойством bean и столбцом DB используется для сохранения, загрузки, построения поисковых запросов и т. Д. Конфигурация Spring DI может быть легко преобразована в настройка кода, как в начале этого вопроса, не так ли? И это используется только для инициализации бина, не так ли? Что означает, что декларативный подход здесь ничего не добавляет, не так ли?

Когда я объявляю hibernate mapping, я просто даю hibernate некоторую информацию, и она работает на ее основе - я не говорю ей, что делать. В случае весны, мое объявление говорит весне точно, что делать - так зачем объявлять это, почему бы просто не сделать это?


ПОСЛЕДНИЕ ОБНОВЛЕНИЯ:
Ребята, многие ответы говорят мне о внедрении зависимостей, которые я ЗНАЮ, ХОРОШО. Вопрос заключается в назначении конфигурации DI вместо инициализации кода - я склонен думать, что инициализация кода короче и понятнее. Единственный ответ, который я до сих пор получил на свой вопрос, заключается в том, что он избегает перекомпиляции при изменении конфигурации. Думаю, мне следует опубликовать еще один вопрос, потому что для меня это большой секрет, почему в этом случае следует избегать компиляции.

Ответы [ 16 ]

1 голос
/ 26 сентября 2008

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

Например, в веб-приложениях модель, представление и контроллеры обычно указываются в отдельных файлах конфигурации. Воспользовавшись декларативным подходом, вы можете загрузить, например: UI-context.xml Model-context.xml Controller-context.xml

Или загрузите с другим пользовательским интерфейсом и несколькими дополнительными контроллерами: AlternateUI-context.xml Model-context.xml Controller-context.xml ControllerAdditions-context.xml

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

1 голос
/ 25 сентября 2008

В мире .NET большинство платформ IoC предоставляют как XML, так и конфигурацию кода.

StructureMap и Ninject, например, используют свободные интерфейсы для настройки контейнеров. Вы больше не обязаны использовать файлы конфигурации XML. Spring, который также существует в .NET, в значительной степени зависит от XML-файлов, поскольку он является его основным интерфейсом основной конфигурации, но все еще можно настраивать контейнеры программно.

0 голосов
/ 12 ноября 2010

Инициализация в файле конфигурации XML упростит вашу работу по отладке / адаптации с клиентом, у которого ваше приложение развернуто на их компьютерах. (Потому что не требует перекомпиляции + замены двоичных файлов)

0 голосов
/ 25 сентября 2008

Одной из наиболее привлекательных причин является " голливудский принцип ": не звоните нам, мы вам позвоним. Компонент не обязан выполнять поиск других компонентов и сервисов сам; вместо этого они предоставляются ему автоматически. В Java это означает, что больше нет необходимости выполнять поиск JNDI внутри компонента.

Кроме того, гораздо проще выполнить модульное тестирование компонента в отдельности: вместо того, чтобы дать ему фактическую реализацию необходимых ему компонентов, вы просто используете (возможно, автоматически сгенерированные) макеты.

0 голосов
/ 25 сентября 2008

Ваш случай очень прост и поэтому не нуждается в контейнере IoC (Inversion of Control), таком как Spring. С другой стороны, когда вы «программируете на интерфейсы, а не на реализации» (что является хорошей практикой в ​​ООП), вы можете иметь такой код:

IService myService;
// ...
public void doSomething() {
  myService.fetchData();
}

(обратите внимание, что тип myService - IService - интерфейс, а не конкретная реализация). Теперь может быть удобно, чтобы ваш контейнер IoC автоматически предоставлял правильный конкретный экземпляр IService во время инициализации - когда у вас много интерфейсов и много реализаций, это может быть неудобно делать вручную. Основные преимущества контейнера IoC (структура внедрения зависимостей):

  • Внешняя конфигурация отображения между интерфейсами и их конкретными реализациями
  • Контейнер IoC обрабатывает некоторые хитрые проблемы, такие как решение сложных графиков зависимостей, управление временем жизни компонента и т. Д.
  • Вы экономите время кодирования, потому что вы предоставляете сопоставления декларативно, а не в процедурном коде
  • Принцип инверсии управления упрощает модульное тестирование, поскольку вы можете заменить реальные реализации поддельными (например, заменить базу данных SQL на оперативную)
0 голосов
/ 25 сентября 2008

Spring также имеет загрузчик свойств. Мы используем этот метод для установки переменных, которые зависят от среды (например, разработка, тестирование, приемка, производство, ...). Это может быть, например, очередь для прослушивания.

Если нет причины, по которой свойство могло бы измениться, также нет причины настраивать его таким образом.

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