Ускоряем Spring Boot: Автоконфигурации

Автоконфигурации в Spring Boot содержат большое количество заранее сконфигурированных компонентов, которые вы можете использовать либо без дополнительного конфигурирования, либо с указанием минимальных настроек вроде информации об адресах используемых сервисов, именах пользователей и паролях.

Это серьёзно ускоряет начало процесса разработки: вы выбираете в зависимостях нужные стартеры, указываете необходимые свойства в файле свойств, и ваш проект уже готов к работе с базами данных, брокерами очередей сообщений и другими компонентами.

Это всё хорошо для процесса разработки, однако для реальной эксплуатации может быть вредно. Контекст приложения, сконфигурированный автоконфигурациями по умолчанию гарантированно будет содержать неиспользуемые компоненты. Приведу пример: нам нужно разработать простой сервис, реализующий набор REST API. Для этого проекта нам понадобится единственный стартер — spring-boot-starter-web.

Если мы сразу запустим приложение с флагом debug, то увидим как минимум 17 используемых автоконфигураций:

  • CodecsAutoConfiguration
  • DispatcherServletAutoConfiguration
  • EmbeddedWebServerFactoryCustomizerAutoConfiguration
  • ErrorMvcAutoConfiguration
  • HttpEncodingAutoConfiguration
  • JacksonAutoConfiguration
  • JmxAutoConfiguration
  • MultipartAutoConfiguration
  • PropertyPlaceholderAutoConfiguration
  • RestTemplateAutoConfiguration
  • ServletWebServerFactoryAutoConfiguration
  • SpringApplicationAdminJmxAutoConfiguration
  • TaskExecutionAutoConfiguration
  • TaskSchedulingAutoConfiguration
  • ValidationAutoConfiguration
  • WebMvcAutoConfiguration
  • WebSocketServletAutoConfiguration

Нужна ли нам в нашем проекте поддержка вебсокетов (WebSocketServletAutoConfiguration) или загрузки файлов (MultipartAutoConfiguration)? А нужен ли компонент RestTemplate? Собираемся ли мы использовать асинхронные вызовы (TaskExecutionAutoConfiguration) или задачи по расписанию (TaskSchedulingAutoConfiguration)? Если ответ на все эти вопросы — «нет», то мы можем сказать, что пять автоконфигураций из семнадцати нам не нужны. Уже в случае с простейшим проектом нам не нужно пять автоконфигураций! В проектах с большим количеством стартеров количество ненужных компонентов и автоконфигураций скорее всего будет расти.

Решить данную проблему можно несколькими способами:

  • Отключить ненужные автоконфигурации
  • Вручную указывать только используемые автоконфигурации
  • Сконфигурировать контекст приложения без автоконфигураций

При этом в рамках разработки одного проекта можно последовательно использовать все три этих способа: последовательно отключая потенциально неиспользуемые конфигурации, определиться со списком используемых, а в дальнейшем на их основе определиться со списком компонентов приложения, которые нужны будут использованы при конфигурировании контекста приложения без использования автоконфигураций.

Отключение ненужных автоконфигураций

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

Отключить ненужные автоконфигурации можно при помощи свойств exclude и excludeName аннотаций @EnableAutoConfiguration, @ImportAutoConfiguration и @SpringBootApplication. Ниже приведён пример.

Указанные автоконфигурации не будут использованы при инициализации контекста приложения. В больших проектах это может немного ускорить скорость запуска приложения, но ускорение, скорее всего, будет невелико.

Указание используемых автоконфигураций вручную

Этот способ подразумевает, что вы уже определились со списком используемых автоконфигураций. В этом случае можно отказаться от использования механизма автоконфигурации, вместо этого указывая необходимые автоконфигурации вручную. Для этого надо избавиться от аннотаций @SpringBootApplication и @EnableAutoConfiguration в коде вашего проекта, а для указания нужных конфигурационных классов использовать аннотации @SpringBootConfiguration и @ImportAutoConfiguration.

Данный способ может быть значительно эффективнее первого, однако стоит помнить, что используемые автоконфигурации всё ещё могут содержать неиспользуемые компоненты.

Ручная конфигурация контекста приложения

Наиболее радикальный и, возможно, наиболее эффективный способ. Применим он только в том случае, когда вы уже наверняка знаете, какие компоненты должны быть сконфигурированы в контексте вашего приложения. Данный способ добавляет большое количество ручной работы и минимизирует выгоду от использования Spring Boot. Наиболее весомый аргумент за этот способ — все компоненты будут сконфигурированы так, как это надо именно вам.

Но этот способ предполагает и хорошее знание и понимание внутреннего устройства Spring, так что обращаться к нему стоит только тогда, когда выгода от ручного конфигурирования контекста очевидна, а ваши знания и опыт позволяют его применять.

Подводя итоги

К конфигурации контекста приложения нужно подходить ответственно, если речь идёт о разработке реального проекта. Наличие большого количества неиспользуемых компонентов в контексте приложения всегда будет иметь отрицательное влияние — их инициализация будет замедлять запуск приложения, а их наличие в контексте приложения будет требовать расхода системных ресурсов, пусть и небольшого.

Как уже было сказано, наличие автоконфигураций в Spring Boot позволяет начать разработку проекта значительно быстрее, но обязательно породит лишние компоненты в контексте приложения. Это не повод отказываться от использования Spring Boot в ваших проектах, но это хороший повод научиться правильно выбирать и использовать автоконфигурации и конфигурировать контекст вашего приложения в зависимости от потребностей.

Полезные ссылки

Официальная документация Spring Boot