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 приложения.