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

Что такое полевая инъекция и как ее избежать?

Я читал в некоторых сообщениях о Spring MVC и Portlets, что вставка поля не рекомендуется. Потому что я пытаюсь получить. Итак, я спросил себя, использую ли я инъекцию в поле, и я не могу ответить на него. Поскольку я понимаю, что инъекция поля - это если вы введете Bean в атрибут с @Autowired следующим образом:

CartController.java:

...
@Autowired
private Cart cart;
...

BookshopConfiguartion.java:

@Configuration
public class BookShopConfiguration {

@Bean
public Cart cart(){
    return new Cart();
}
//more configuration

My Cart.java используется для хранения и предоставления информации о книгах в корзине.

Во время моего исследования я прочитал о введении конструктора:

MyComponent.java:

...
public class MyComponent{
private Cart cart;

@Autowired
public MyComponent(Cart cart){
   this.cart = cart;
}
...

Каковы преимущества и недостатки обоих этих типов инъекций?


ИЗМЕНИТЬ 1: Поскольку этот вопрос отмечен как дубликат этого вопроса, я проверил его. Потому что нет никаких примеров кода ни в вопросе, ни в ответах, которые мне не понятны, если я правильно с моим догадкой, какой тип инъекции я использую.

4b9b3361

Ответ 1

Типы инъекций

Есть три варианта, как зависимости могут быть введены в bean: 1. Через конструктор 2. Через сеттеры или другие методы 3. Через отражение непосредственно в поля

Вы используете опцию 3 - это когда вы используете @Autowired непосредственно в своем поле.


Рекомендации по инъекциям

Общая рекомендация как рекомендуется также Spring (см. раздел DI на основе конструктора или сеттера):

  • Для обязательных зависимостей или при стремлении к неизменности используйте конструкторскую инъекцию
  • Для опциональных или изменчивых зависимостей используйте инъекцию установщика
  • Избегайте инъекции в большинстве случаев.

Недостатки ввода в поле

Причины, по которым наводнение в поле зрения неодобрительно, следующие:

  • Вы не можете создавать неизменяемые объекты, как при инсталляции конструктора
  • Ваши классы имеют плотную связь с контейнером DI и не могут использоваться вне него
  • Ваши классы не могут быть созданы (например, в модульных тестах) без отражения. Для их создания требуется контейнер DI, что больше похоже на интеграционные тесты.
  • Ваши реальные зависимости скрыты снаружи и не отражаются в вашем интерфейсе - конструкторы или методы.
  • Очень легко иметь 10 зависимостей. Если вы использовали инъекцию конструктора, наличие конструктора с 10 аргументами будет сигнализировать о том, что что-то подозрительное. Но вы можете добавлять введенные поля, используя полевую инъекцию на неопределенный срок. Слишком много зависимостей - это красный флаг, который класс обычно делает больше чем одно, и это может быть нарушение принципа единой ответственности.

Заключение

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


Дополнительная литература

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

Ответ 2

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

Ввод конструктора

Плюсы:

  • Лучшая тестируемость. Вам не нужна какая-либо насмешливая библиотека или контекст Spring в модульных тестах. Вы можете создать объект, который вы хотите протестировать, с помощью нового ключевого слова. Такие тесты всегда быстрее, потому что они не полагаются на механизм отражения. (Этот вопрос был задан через 30 минут. Если автор использовал инъекцию конструктора, он бы не появился).
  • Неизменность. После установки зависимостей они не могут быть изменены.
  • Безопасный код. После выполнения конструктора ваш объект готов к использованию, так как вы можете проверить все, что было передано в качестве параметра. Объект может быть либо готов, либо нет, между ними нет состояния. При инъекции поля вы вводите промежуточный шаг, когда объект является хрупким.
  • Чистое выражение обязательных зависимостей. В этом случае полевая инъекция неоднозначна.
  • Заставляет разработчиков задуматься о дизайне. dit написал о конструкторе с 8 параметрами, что на самом деле является признаком плохой конструкции и объект анти-шаблона объекта God. Не имеет значения, имеет ли класс 8 зависимостей в своем конструкторе или в полях, это всегда неправильно. Люди более неохотно добавляют больше зависимостей к конструктору, чем через поля. Он работает как сигнал к вашему мозгу, что вы должны остановиться на некоторое время и подумать о своей структуре кода.

Минусы:

  • Больше кода (но современные IDE облегчают боль).

В принципе, инъекция поля противоположна.

Ответ 3

Вопрос вкуса. Это ваше решение.

Но я могу объяснить, почему я никогда не использую инъекцию конструктора.

  • Я не хочу реализовывать конструктор для всех моих @Service, @Repository и @Controller beans. Я имею в виду, что около 40-50 beans или больше. Каждый раз, когда я добавляю новое поле, мне придется расширять конструктор. Нет. Я не хочу этого, и мне не нужно.

  • Что делать, если ваш Bean (служба или контроллер) требует ввода большого количества других beans? Конструктор с 8 параметрами очень уродлив.

  • Если я использую CDI, конструктор меня не касается.


ИЗМЕНИТЬ: Войтех Рузичка сказал:

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

Да. Теория и реальность. Вот пример: DashboardController, сопоставленный одному пути *:8080/dashboard.

My DashboardController собирает много информации из других служб, чтобы отображать их на странице обзора панели/системы. Мне нужен этот единственный контроллер. Поэтому я должен защищать только этот путь (базовый фильтр авторизации или пользователя).