Перейти к содержанию

Spring Boot

Spring Boot - надстройка над Spring, которая собирает совместимые версии библиотек, сама настраивает типовые компоненты по содержимому classpath и запускает приложение как обычный jar со встроенным веб-сервером. Появился в 2014 году. Boot - упрощение, а не обязательная часть: со Spring можно работать вручную (см. Spring без Boot).


Какую проблему решает

  • Библиотеки и фреймворки экосистемы Spring разрабатывают разные люди
  • Между ними тесные связи, и каждая обновляется по своему графику
  • Отсюда постоянные проблемы совместимости версий
  • У части библиотек сложная конфигурация

Boot закрывает это так:

  • Совместимые версии - стартеры и BOM фиксируют набор версий, которые проверены вместе
  • Типовая конфигурация - автоконфигурация настраивает компоненты сама
  • Просто запустить - встроенный servlet-контейнер, обычно Tomcat. Приложение стартует через java -jar app.jar

Что больше не нужно делать руками:

  • настраивать сканирование пакетов на бины
  • конфигурировать Spring Web MVC и другие модули Spring Framework
  • поднимать отдельный сервер приложений и деплоить на него приложение

Автоконфигурация

Автоконфигурация - набор @Configuration-классов Boot, которые срабатывают по условиям: есть ли класс в classpath, есть ли уже такой бин, задано ли свойство.

  • @ConditionalOnClass - библиотека подключена
  • @ConditionalOnMissingBean - пользователь не объявил свой бин. Свой бин всегда побеждает автоконфигурацию
  • @ConditionalOnProperty - включено свойство
  • список автоконфигураций Boot 3 лежит в META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

Примеры:

  • в classpath есть spring-webmvc - Boot настраивает DispatcherServlet (см. MVC и Boot)
  • подключён spring-boot-starter-data-jpa - Boot настраивает DataSource, EntityManagerFactory и менеджер транзакций (см. Spring Data)

Диагностика: запусти приложение с --debug, Boot напечатает отчёт, какие автоконфигурации сработали и почему.

java -jar app.jar --debug

Стартеры и запуск

Стартер - зависимость-набор: подключаешь одну, получаешь библиотеки и их согласованные версии. spring-boot-starter-web, spring-boot-starter-data-jpa, spring-boot-starter-security.

@SpringBootApplication - аннотация главного класса. Включает @Configuration, @EnableAutoConfiguration и @ComponentScan от пакета этого класса.

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);   // создаёт и запускает контекст
    }
}

Встроенный сервер - Tomcat, Jetty или Undertow живут внутри приложения как библиотека. Отдельно сервер не ставят.

Деплой в WAR. Если Boot-приложение всё же нужно развернуть на внешнем Tomcat, главный класс наследует SpringBootServletInitializer, а сборка делается в war.


Конфигурация

  • Boot читает свойства из application.yml или application.properties в resources
  • Для профиля, отличного от default, дополнительно читает application-{profile}.yml
  • Один файл задаёт порты, источники данных, параметры безопасности и т.д.
  • Вместо россыпи @Value можно собрать группу свойств в класс с @ConfigurationProperties
@ConfigurationProperties(prefix = "com.behl.salamanca")
public record JwtConfigurationProperties(String secretKey, Duration accessTokenTtl) {
}

@Configuration
@EnableConfigurationProperties(JwtConfigurationProperties.class)   // регистрирует класс свойств как бин
public class JwtConfig {
}

См. Environment, профили и свойства.


Spring без Boot

Без Boot всё, что Boot делает сам, настраивают руками.

  1. Создать контейнер - явно создать ApplicationContext (см. Как стартует контекст).
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
  1. Объявить все бины - в Java-конфиге или XML (см. Бины).

  2. Зарегистрировать DispatcherServlet - в web.xml или через WebApplicationInitializer.

<web-app>
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <!-- конфиг веб-контекста этого сервлета -->
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring-web-config.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>
  1. Настроить остальные модули - например Spring Security в XML. Это старый стиль, сейчас Security настраивают бином SecurityFilterChain (см. Spring Security).
<http>
    <intercept-url pattern="/admin/**" access="ROLE_ADMIN"/>
    <form-login login-page="/login"/>
</http>
<authentication-manager>
<authentication-provider>
    <user-service>
        <!-- пароль открытым текстом - только для учебного примера -->
        <user name="admin" password="admin" authorities="ROLE_ADMIN"/>
    </user-service>
</authentication-provider>
</authentication-manager>
  1. Развернуть WAR на внешнем сервере: Tomcat или Jakarta EE сервер (WildFly, Payara).

Spring на Jakarta EE сервере. IoC-контейнер Spring от сервера не зависит, но может с ним сосуществовать:

  • Spring управляет своими бинами, сервер - JNDI, пулом соединений, иногда транзакциями (JTA) и безопасностью
  • ресурсы сервера Spring получает через JNDI, например @Resource DataSource dataSource
  • рядом может работать CDI сервера, но это два разных контейнера
Со Spring Boot Без Spring Boot
Создание контейнера Автоматически, SpringApplication.run() Ручной вызов ApplicationContext
Конфигурация модулей Автоматическая по classpath Всё вручную
Сервер Встроенный: Tomcat, Jetty, Undertow Внешний сервер, деплой WAR
Настройки Один application.properties или .yml Много XML и Java-конфигов
Скорость разработки Высокая Ниже из-за ручной настройки

Когда Boot:

  • нужно быстро поднять и развернуть приложение
  • микросервисы, REST API, небольшие веб-приложения
  • нужно меньше настроек и больше готовых решений

Когда без Boot:

  • нужен полный контроль над конфигурацией
  • Spring встраивают в существующую корпоративную архитектуру
  • обязателен деплой на Jakarta EE сервер (WildFly, Payara)

TODO

  • Spring Boot starter - разобрать подробно
  • Конфигурирование - порядок источников свойств в Boot
  • Spring Boot Application - что происходит внутри SpringApplication.run()
  • @ConfigurationProperties - подробно, с валидацией и вложенными свойствами