Spring Boot

Spring Boot собирает типовое Spring-приложение из зависимостей, автоконфигураций и внешних настроек. Он не заменяет Spring Framework: контейнер, DI, AOP и транзакции остаются теми же, но стартовая конфигурация становится короче.

Стартеры

Стартер — согласованный набор зависимостей для конкретной задачи. Например, spring-boot-starter-web добавляет Spring MVC, JSON-сериализацию и встроенный servlet-контейнер. Bean Validation подключают отдельным spring-boot-starter-validation. Стартер почти не содержит исполняемого кода; основную работу делают библиотеки и автоконфигурация.

Boot управляет совместимыми версиями через dependency management. Версию отдельной библиотеки стоит переопределять только после проверки совместимости со всей выбранной версией Boot.

Как работает автоконфигурация

@SpringBootApplication объединяет:

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
public @interface SpringBootApplication {}

При запуске Boot импортирует классы автоконфигурации. Они создают бины только при выполнении условий:

  • нужный класс есть в classpath — @ConditionalOnClass;
  • пользователь ещё не объявил свой бин — @ConditionalOnMissingBean;
  • задано свойство — @ConditionalOnProperty;
  • приложение относится к нужному типу — например, servlet или reactive.

Поэтому автоконфигурация «отступает», когда приложение задаёт собственную реализацию. Если бин неожиданно появился или не появился, полезно включить debug-отчёт условий и проверить classpath, properties и уже зарегистрированные бины.

Внешняя конфигурация

Значения можно хранить в application.yml, профильных файлах, переменных окружения, системных свойствах и аргументах запуска. Источники имеют приоритет: значение из более приоритетного источника заменяет менее приоритетное.

app:
  client:
    base-url: ${CLIENT_BASE_URL}
    connect-timeout: 2s
    retries: 3

Для группы связанных настроек лучше использовать типизированный класс:

@ConfigurationProperties("app.client")
@Validated
public record ClientProperties(
        @NotNull URI baseUrl,
        @NotNull Duration connectTimeout,
        @Min(0) int retries
) {}

@ConfigurationProperties поддерживает relaxed binding: APP_CLIENT_BASE_URL, app.client.base-url и близкие варианты связываются с одним полем. Секреты не следует хранить в репозитории; приложение получает их из окружения или хранилища секретов.

@Value удобен для одного простого значения, но хуже подходит для большой группы: нет единого объекта, сложнее валидация и тестирование.

Встроенный сервер и запуск

Executable JAR содержит приложение и встроенный сервер. SpringApplication.run создаёт ApplicationContext, применяет конфигурацию, поднимает сервер и публикует события запуска.

@SpringBootApplication
@ConfigurationPropertiesScan
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

WAR и внешний контейнер всё ещё возможны, но для автономного сервиса обычно проще JAR.

Наблюдаемость

Actuator добавляет служебные endpoints: состояние, метрики, сведения о конфигурации и другие диагностические данные. Публично открывают только необходимое; служебные endpoints защищают отдельно от пользовательского API.

Тестовые срезы

  • @SpringBootTest поднимает почти весь контекст;
  • @WebMvcTest проверяет MVC-слой;
  • @DataJpaTest поднимает JPA-часть;
  • обычный unit-тест не должен создавать Spring-контекст без необходимости.

Срез быстрее и точнее показывает, какой слой сломан. Полный тест нужен для проверки сборки компонентов вместе.

Частые сбои

  • два бина одного типа без @Qualifier или @Primary;
  • конфигурационный класс лежит вне component scan;
  • профиль не активирован или переменная окружения названа неверно;
  • пользовательский бин отключил ожидаемую автоконфигурацию;
  • блокирующий стартер попал в reactive-приложение;
  • обновили одну транзитивную библиотеку и нарушили согласованный набор версий.

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

Чем Spring Boot отличается от Spring? Spring даёт программную модель и контейнер; Boot задаёт соглашения, автоконфигурацию, стартеры и удобный запуск.

Автоконфигурация всегда создаёт бин? Нет, она управляется условиями и обычно уступает пользовательской конфигурации.

Почему приложение может стартовать медленно? Большой classpath, множество бинов, сканирование, миграции, сетевые проверки и тяжёлая инициализация. Сначала измеряют этапы старта, затем оптимизируют.

Связанные заметки: Spring, Spring Context, Жизненный цикл бина, Конфигурация и сборка Spring приложения.