Как стать автором
Обновить

Еще одна статья о DI в Spring Boot


Как сказал один мудрец: вечно смотреть можно на три вещи: как течет вода, как горит огонь и как кто-то пишет очередную стать о DI в Spring Boot. Сегодня я сделаю попытку коротко описать всю эту петрушку.

DI (Dependency Injection, внедрение зависимости) — процесс при котором построение одного объекта, предоставляется внешнему объекту. Или точнее это то место, где зависимость будет внедрена другим объектом. Понятнее будет на примере. Пусть у нас есть класс «Автомобиль» у него есть поле класса «Двигатель». Место где «Двигатель» будет инициализирован в «Автомобиле» и будет внедрением зависимости.

В Spring Boot существует 4 типа DI:

  1. Как поле класса
  2. Как приватное поле класса (прочитали что так можно делать DI, теперь забудьте — способ 2 ЗЛО!)
  3. С помощью setter
  4. С помощью конструктора

DI с помощью «сеттера» до сих пор остается местом споров. Это связано с другой особенностью Spring Boot — Ioc (Inversion of Controll, инверсия контроля). IoC — передача управления. Обычно программист сам решает когда вызывать ту или иную процедуру, делать DI и т.п. В Spring Boot — это делает IoC — инициализация и вызовы процедур в Runtime. Получается, что используя DI с помощью «сеттера» вы не можете знать в какой именно момент вы зависимость будет внедрена.

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

DI с помощью конструктора — наиболее предпочтительный способ осуществления DI. Связывание будет осуществлено в момент создания объекта и вы точно будете знать когда именно IoC осуществит вызов.

В Spring Boot в месте, где будет осуществлена инъекция необходимо ставить аннотацию @Autowired (автосвязывание). Однако, если вы используете DI с помощью конструктора использовать эту аннотацию необязательно.

Ниже я приведу пример каждого способа DI кроме 2, ведь, мы на светлой стороне силы, так?

DI как поле класса

@Controller
public class PropertyInjectedController {

    @Autowired
    public GreetingServiceImpl greetingService;

    public String sayHello(){
        return greetingService.sayGreeting();
    }

}

Недостатки:

  1. Публичное поле
  2. Нельзя указать интерфейс, только конкретную реализацию. Использовать DI интерфейсов это хорошая практика, дающая много преимуществ и открывающая перед вами другие инструменты Spring Boot для внедрения зависимостей, но об этом как-нибудь в другой раз.

DI как сеттер

@Controller
public class SetterInjectedController {
    private GreetingService greetingService;

    public String sayHello(){
        return greetingService.sayGreeting();
    }

    @Autowired
    public void setGreetingService(GreetingService greetingService) {
        this.greetingService = greetingService;
    }
}

Главный недостаток описан выше.

DI как конструктор

@Controller
public class ConstructorInjectedController {

    private GreetingService greetingService;

    @Autowired
    public ConstructorInjectedController(GreetingService greetingService) {
        this.greetingService = greetingService;
    }

    public String sayHello(){
        return greetingService.sayGreeting();
    }
}

Какой из способов использовать — решать вам. Главное, чтобы это был DI с помощью конструктора.
Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.