Фреймворк

Фреймворк задаёт каркас выполнения и точки расширения. Прикладной код регистрируется в нём, а затем фреймворк вызывает наш код. Это часто называют inversion of control.

@RestController
final class HealthController {
    @GetMapping("/health")
    Status health() {
        return new Status("UP");
    }
}

Метод не содержит main и сам не читает сокет. Spring создаёт объект, связывает маршрут и вызывает метод при HTTP-запросе.

Фреймворк и библиотека

БиблиотекаФреймворк
наш код вызывает её APIона управляет жизненным циклом и вызывает callbacks
локальная зависимостьархитектурный каркас приложения
заменить обычно прощезамена затрагивает интеграционные границы

Граница не абсолютна: Spring включает множество библиотек, а библиотека может принимать callbacks.

Что фреймворк обычно задаёт

  • lifecycle объектов;
  • конфигурацию и dependency injection;
  • обработку входящих событий;
  • интеграцию с инфраструктурой;
  • extension points и соглашения;
  • обработку ошибок и наблюдаемость.

Цена удобства — скрытый control flow, ограничения модели и стоимость обновлений. Полезно держать доменную логику в обычных классах, а framework-код — на границах.

Ошибки

  • наследоваться от внутренних классов без стабильного контракта;
  • ставить аннотации на каждый доменный объект;
  • не понимать, где proxy, thread и transaction boundary;
  • считать default-настройки частью бизнес-требований.

На собеседовании

Что такое inversion of control? Фреймворк управляет выполнением и вызывает зарегистрированный пользовательский код.

Главное отличие от библиотеки? Направление управления, хотя граница не всегда строгая.

Почему фреймворк усложняет отладку? Часть вызовов, объектов и proxy создаётся неявно.

Как уменьшить зависимость? Изолировать adapters и не тащить API фреймворка в ядро модели.

Связано: Основные сущности Spring Framework, Spring Dependency Injection и Inversion of Control, Разница между BeanFactrory и ApplicationContext.