Spring Dependency Injection

Spring - найпопулярніший фреймворк в Java. Його знання вимагають практично на кожній співбесіді. І, скоріш за все, з ним ви почнете ваш пет-проект.

Spring починався з одного модуля, який реалізовував шаблон Dependency Injection(Вставка Залежностей). Простими словами - DI вміє створювати об'єкти, які залежать один від одного і вставляти одні об'єкти в інші.

Розглянемо простий приклад. Є клас DatabaseConnection:

package ua.com.java4beginners;

public class DatabaseConnection {

  @Override
  public String toString() {
    return "I am DatabaseConnection - " + hashCode();
  }
}

І є клас ReportService що від нього залежить:

package ua.com.java4beginners;

import org.springframework.beans.factory.annotation.Autowired;

public class ReportService {
  public DatabaseConnection connection;

  @Autowired
  public ReportService(DatabaseConnection connection) {
    this.connection = connection;
  }

  public DatabaseConnection getDatabaseConnection() {
    return connection;
  }

  @Override
  public String toString() {
    return "I am ReportService - " + hashCode();
  }
}

Щоб отримати повноцінний об'єкт ReportService нам прийдеться виконати наступне.

public static void main(String[] args) {
  DatabaseConnection con = new DatabaseConnection();
  ReportService rs = new ReportService(con);
}

Це все може зробити за нас Spring.

  1. Створюємо новий maven проект.
  2. Додаємо в pom.xml
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.4.RELEASE</version>
        </dependency>
    </dependencies>
    
  3. Додаємо класи DatabaseConnection, ReportService.
  4. Створюємо клас App:

    package ua.com.java4beginners;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    
    public class App {
        public static void main( String[] args ) {
            String package = "ua.com.java4beginners"; // пакет який спрінг має просканувати
            ApplicationContext ctx = new AnnotationConfigApplicationContext(package);
            ReportService rs = ctx.getBean(ReportService.class);
    
            System.out.println(rs);
            System.out.println(rs.getDatabaseConnection());
        }
    }
    

    Анотація @Autowired вказує спрінгу знайти і створи залежний об'єкт. Цю анотацію можна "повісити" на поле і прибрати конструктор. Ефект буде аналогічним.

    Такий підхід сильно спрощує процес тестування. Ми зможемо легко замінити реальний  DatabaseConnection, що працює з базою, на об'єкт-заглушку. Так ми зможемо протестувати об'єкти в ізоляції(незалежно один від одного).

    Другою перевагою DI є слабка зв'язаність коду. Він легше піддається рефакторінгу. Spring, в цьому випадку, працює як "клей" що з'єднує всі частини програми до купи.

Spring DI - це лише маленька частина того що є в Spring Framework. В наступних статтях подивимось на Spring Mvc, Boot, Data, Integration, Security та інші.