TGViewer
Java: fill the gaps Java: fill the gaps @java_fillthegaps · 12.3K subscribers
Post #342 7.24K
Чем отличаются Dependency injection, Dependency invertion и Inversion of Control

Прошлый пост про Liskov, как говорится, "взорвал мой директ", поэтому на этой неделе расскажу про ещё два популярных принципа.

Сегодня про букву D из SOLID — Dependency Inversion. Что это, и чем отличается от Dependency injection и Inversion of Control. Понимание пригодится на собеседованиях, при чтении статей по дизайну и архитектуре.

Будем разбираться на простом примере: класс Service записывает логи в файл через класс FileLogger:

class FileLogger {…}
class Service {
FileLogger logger=new FileLogger();
}

Сделаем код чуть лучше с помощью разных принципов:

1️⃣ Dependency injection
— компоненты создаются не внутри класса, а где-то в другом месте.

Как реализовать: перенести инициализацию логгера в конструктор или сеттер:

class Service {
FileLogger logger;
Service (FileLogger logger) {
this.logger=logger;
}
}

✅ Класс занимается только своей бизнес-логикой
✅ Можно вынести всю конфигурацию в одно место. Или спихнуть часть забот фреймворку, например, Spring

⚔️Историческая справка
Когда Spring ещё не был популярен, в проектах использовался паттерн Service Locator.

Суть: компоненты создаются в классе ServiceLocator, а другие классы получают к ним доступ через статические методы:

class ServiceLocator {
static Logger logger = …
static Logger getLogger() {
return logger;
}
}

class Service {
Logger logger=ServiceLocator.getLogger();
}

2️⃣ Dependency invertion (D из SOLID)
▫️Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций
▫️Модули верхнего уровня не должны зависеть от модулей нижнего уровня. Оба должны зависеть от абстракции

Как реализовать: использовать интерфейс логгера, а не конкретный класс

interface Logger {…}
class FileLogger implements Logger {…}

class Service {
Logger logger=new FileLogger();
}

✅ Интерфейс проще использовать, так как методов меньше
✅ Реализацию легко заменить
✅ Оба класса проще тестировать

Термин "абстракция" используется, потому что SOLID не привязан только к джаве. Группу методов можно выделить в интерфейс, в абстрактный класс и даже в обычный класс. Но интерфейс — наилучший вариант

3️⃣ IoC - Inversion of Control
В маленьких программах жизнь начинается в методе main. Программист создаёт объекты и вызывает их методы, все шаги явно прописаны.

Inversion of Control — это когда ход выполнения программы задаёт фреймворк. Например, Spring создаёт объекты, принимает запросы и не даёт программе завершиться.

Как реализовать: использовать аннотации фреймворка

@Component class FileLogger {…}
@Component class Service {
@Autowired
FileLogger logger;
}

✅ Меньше скучного кода
✅ Низкая связность — код легко читать, менять и тестировать

Резюме:
🔸Dependency injection — класс не создаёт компоненты напрямую, они передаются через конструктор или сеттер
🔸Dependency invertion — класс работает с другими компонентами через интерфейс
🔸Inversion of Control — ход программы задаёт фреймворк

❗️Ответ на вопрос перед постом:
Это словоблудие относится к Dependency injection
  • 👍 6
  • ❤ 1
More from @java_fillthegaps
  1. Apr 30, 2026Get Your Hands Dirty on Clean Architecture: отзыв на книгу Когда я подняла тему чистой арх…
  2. Apr 27, 2026​Clean Architecture: отзыв на книгу Наконец-то дочитала книгу Clean Architecture Роберта М…
  3. Mar 4, 2026Как переиспользовать контекст в интеграционных тестах Сегодня расскажу базовый минимум для…
  4. Mar 4, 2026Post #660
  5. Mar 4, 2026Тестовый контекст поднимается 2 минуты. У нас 4 класса с интеграционными тестами, их конфи…
  6. Feb 25, 2026Чистая архитектура. Главы 3-5 Продолжаем спидран по Clean Architecture Роберта Мартина. ⭐️…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →