Учебники

Весна — Внедрение Зависимости

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

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

public class TextEditor {
   private SpellChecker spellChecker;
   
   public TextEditor() {
      spellChecker = new SpellChecker();
   }
}

Здесь мы создали зависимость между TextEditor и SpellChecker. В сценарии инверсии управления мы вместо этого сделали бы что-то вроде этого —

public class TextEditor {
   private SpellChecker spellChecker;
   
   public TextEditor(SpellChecker spellChecker) {
      this.spellChecker = spellChecker;
   }
}

Здесь TextEditor не должен беспокоиться о реализации SpellChecker. SpellChecker будет реализован независимо и будет предоставлен TextEditor во время создания экземпляра TextEditor. Вся эта процедура контролируется Spring Framework.

Здесь мы удалили тотальный контроль из TextEditor и сохранили его где-то еще (например, файл конфигурации XML), а зависимость (т.е. класс SpellChecker) вводится в класс TextEditor через конструктор класса . Таким образом, поток управления был «инвертирован» с помощью Dependency Injection (DI), потому что вы фактически делегировали зависимости некоторой внешней системе.

Второй метод внедрения зависимости — через Setter Methods класса TextEditor, где мы создадим экземпляр SpellChecker. Этот экземпляр будет использоваться для вызова методов установки для инициализации свойств TextEditor.

Таким образом, DI существует в двух основных вариантах, и в следующих двух подразделах будут рассмотрены оба примера:

Sr.No. Тип и описание внедрения зависимостей
1 Внедрение зависимостей на основе конструктора

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

2 Внедрение зависимостей на основе установки

DI на основе установки выполняется контейнером, вызывающим методы setter для ваших bean-компонентов после вызова конструктора без аргументов или статического метода фабрики без аргументов для создания экземпляра вашего bean-компонента.

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

DI на основе установки выполняется контейнером, вызывающим методы setter для ваших bean-компонентов после вызова конструктора без аргументов или статического метода фабрики без аргументов для создания экземпляра вашего bean-компонента.

Вы можете смешивать как DI на основе конструктора, так и на основе Setter, но рекомендуется использовать аргументы конструктора для обязательных зависимостей и setters для необязательных зависимостей.

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