Подтвердить что ты не робот

Setter DI vs. Constructor DI в Spring?

Spring имеет два типа DI: setter DI и конструкцию DI.

DI на основе конструктора фиксирует порядок, в котором должны быть введены зависимости. Сеттер, основанный на DI, не предлагает этого.

Дистрибутор на основе Setter помогает нам вводить зависимость только тогда, когда это требуется, а не требовать ее во время построения.

Я не вижу других существенных различий, так как оба типа Spring DI предоставляют одни и те же функции - как setter, так и конструктор DI вставляют зависимость при запуске кода. Конечно, конструктор DI будет делать это через конструктор, в то время как setter DI будет делать это через сеттер сразу после построения объекта, но это не имеет никакого значения для разработчика с точки зрения производительности и т.д. Оба они также предлагают средства для указания порядка инъекции зависимостей.

Я ищу сценарий, в котором один дает отличное преимущество перед другим или где один тип полностью непригоден.

4b9b3361

Ответ 1

Когда дело доходит до Spring конкретных плюсов и минусов:

  • Ввод конструктора (из определения) не позволяет создавать круговые зависимости между beans. Это ограничение на самом деле является преимуществом впрыска конструктора - Spring может разрешать циклические зависимости, когда используется инъекция setter, даже если вы даже не заметили.

  • С другой стороны, если вы используете инъекцию конструктора, CGLIB не может создать прокси-сервер, заставляя вас использовать прокси-серверы на основе интерфейса или конструктор no-arg. См.: SPR-3150

Ответ 2

Вы должны принимать решения, основываясь на соображениях проектирования, а не на инструментах (Spring). К сожалению, Spring обучил нас использовать инъекцию setter, потому что, когда она была изначально задумана, в Java не было такой вещи, как "аннотация", а в XML, установка вставки и работает намного лучше. Сегодня мы освобождаемся от этих ограничений, что позволяет ему снова стать дизайнерским решением. Ваш beans должен использовать инъекцию конструктора для любых зависимостей, которые требуются bean и инсталлятором установки для зависимостей, которые являются необязательными и имеют разумный по умолчанию, более или менее, поскольку OOD рассказывал нам с самого начала.

Ответ 3

Инъекция конструктора: Мы вводим зависимости через конструктор.

Обычно мы можем использовать для обязательных зависимостей.

Если вы используете инъекцию конструктора, есть один недостаток, называемый "Круговая зависимость".

Циркулярная зависимость: Предположим, что A и B. A зависит от B. B зависит от A. В этом конструкторе инъекция будет неудачной. В это время полезно использовать инъекцию Setter.

Если состояние объекта не противоречиво, он не будет создавать объект.

Инъекция сеттера: Мы вводим зависимости через методы Setter.

Это полезно для не обязательных зависимостей.

Возможно повторно вводить зависимости, используя Инсталляция Setter. Невозможно в Встраивание конструктора. >

Ответ 4

Ну, это кажется полемическим обсуждением. Первое, что нужно решить, - это то, что Вставка поля отличается от инъекции Setter:

Полевая инъекция:

@Autowired
private SomeService someService;

Ввод сеттера:

@Autowired
public void setSomeService(SomeService someService) {
    this.someService = someService;
}

Но для меня они разделяют некоторые проблемы. И, мой любимый, инсталляция конструктора:

@AutoWired
public MyService(SomeService someService) {
    this.someService = someService;
}

У меня есть следующие причины полагать, что инжекция конструктора лучше, чем установка set/field:

  • Предотвращение круговых зависимостей: Spring может обнаруживать круговые зависимости между Beans, как объяснил @Tomasz. См. Также Spring Команда, говорящая, что.
  • Зависимости класса очевидны.. Зависимости класса очевидны в конструкторе, но скрытые с инъекцией поля/сеттера. Я чувствую, что мои занятия похожи на "черный ящик" с инъекцией поля/сеттера. И есть (по моему опыту) тенденция к разработчикам не беспокоиться о классе со многими зависимостями, что очевидно, когда вы пытаетесь высмеять класс с использованием встраивания конструктора (см. Следующий пункт). Проблема, которая беспокоит разработчиков, скорее всего, будет решена.
  • Легко и надежно обманывать: по сравнению с полевым вводом, проще высмеивать unit test, потому что вам не нужен какой-либо контекстной макет или техника отражения, чтобы достичь объявленного закрытого Bean внутри класса, и вы не будете обмануто им. Вы просто создаете экземпляр класса и передаете издеваемое beans. Простота понимания и простота.
  • Инструменты качества кода могут помочь вам. Инструменты, такие как Sonar, могут предупредить вас о том, что класс становится слишком сложным, потому что класс с большим количеством параметров, вероятно, слишком сложный класс и нуждается в каком-то рефакторе.
  • Лучший и независимый код. С меньшим разбросом @AutoWired среди вашего кода ваш код меньше зависит от структуры. Я знаю, что возможность простого изменения структуры DI в проекте не оправдывает это (кто это делает, правильно?). Но это показывает для меня лучший код (я узнал это в жесткий путь с помощью EJB и поисковых запросов). И с помощью Spring вы даже можете удалить аннотацию @AutoWired, используя инъекцию конструктора.
  • Больше аннотаций - это не всегда правильный ответ: Для some причины, я действительно пытаюсь использовать аннотации только тогда, когда они действительно полезны.

Если вы ищете дополнительную информацию, я рекомендую эту старую (но все же релевантную) статью из Spring Блог, рассказывающий нам, почему они используйте так много инъекций установщика и рекомендацию использовать инъекцию конструктора:

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

И эта заметка о том, почему они считают, что конструктор более подходит для кода приложения:

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

Заключительные мысли

Если вы не уверены в преимуществах конструктора, возможно, идея смешать setter (не поле) с инжектором конструктора является опцией, как объясняется Spring команда:

Поскольку вы можете смешивать оба, DI-конструктор и Setter-based, это хороший эмпирическое правило для использования аргументов конструктора для обязательных зависимостей и сеттеры для необязательных зависимостей

Но помните, что полевая инъекция - это, вероятно, один который следует избегать среди трех.

Ответ 5

Предпочитайте инъекцию сеттера.

Подумайте, что будет без spring (как заметил Райан). Не могли бы вы передать зависимости в конструкторе? Если слишком много зависимостей, это кажется неправильным. С другой стороны, конструктор может использоваться для обеспечения правильного состояния объекта - требует всех зависимостей и проверки, не являются ли они ненужными.

Прокси - это еще одна вещь (как заметил Томаш) - вам понадобится конструктор фиктивного типа, который победит всю идею.

Существует 3-й вариант btw - инъекции поля. Я обычно использую это, хотя это не такое хорошее дизайнерское решение, потому что оно сохраняет дополнительный сеттер, но если он используется вне spring, мне придется добавить установщик.

Ответ 6

нет, даже инжекция конструктора происходит, инъекция все еще работает, но только ограниченная инициализация, инъекция установщика является необязательной и гибкой. но обычно это может быть для класса параметров, a spring bean с другим spring beans

Ответ 7

Так как вы можете смешивать оба, Конструктор DI - и DI файл с настройками, это хорошее правило для использования аргументы конструктора для обязательных зависимостей и сеттеров для необязательных зависимостей.


Примечание о том, что использование аннотации @Required для сеттера может использоваться для создания требуемых зависимостей сеттера.