В чем разница между IoC (Inversion of Control) и DI (Dependency Injection)?

«В чем разница между IoC (Inversion of Control) и DI (Dependency Injection)?» — вопрос из категории Spring, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

IoC (Инверсия управления) — это общий архитектурный принцип, при котором управление потоком выполнения или вызовом компонентов делегируется внешнему фреймворку или контейнеру, а не контролируется самим кодом приложения.

DI (Внедрение зависимостей) — это конкретный шаблон проектирования, реализующий IoC. Зависимости объекта не создаются им самим, а "внедряются" извне (обычно контейнером).

Ключевое отличие: DI — это частный случай IoC. IoC может быть реализован и другими способами (например, через шаблон Factory или Service Locator).

Пример DI в Spring:

// Зависимость
interface Repository { /* ... */ }

// Сервис, получающий зависимость через конструктор (Constructor Injection)
@Service
public class MyService {
    private final Repository repository;

    @Autowired // Контейнер Spring внедрит реализацию Repository
    public MyService(Repository repository) {
        this.repository = repository; // Зависимость предоставлена извне
    }
}

Почему это важно: DI делает код более тестируемым, слабосвязанным и управляемым, так как зависимости можно легко подменить (например, на моки в unit-тестах).