Spring является самым популярным инструментом при разработке промышленных приложений на Java – от больших монолитных приложений до микросервисов. Сразу стоит отметить, что под термином Spring мы понимаем уже не столько Spring Framework, сколько экосистему и Spring Boot – всё то, что позволяет нам "легко и непринужденно" использовать самые распространенные библиотеки из мира Java, зачастую даже не разбираясь в их настройках (всё настроено уже за нас).

Разработка на Java — Инфографика «Экосистема разработки в 2021 году» | JetBrains: Developer Tools for Professionals and Teams
Разработка на Java — Инфографика «Экосистема разработки в 2021 году» | JetBrains: Developer Tools for Professionals and Teams

Spring Boot настолько упрощает разработку, что достаточно часто его изучают уже с минимальными знаниями Java, воспринимая как «светлую магию» аннотации, которые «обучают» методы обычных классов обрабатывать HTTP-запросы и т.д.

В том числе, этому способствует большое количество курсов (как онлайн, так и оффлайн), где за пару десятков часов (или даже всего за пару часов) нам «отдадут» контент, содержащий все ключевые и популярные слова из вакансий: Spring, Spring Boot, REST, Hibernate, JPA, Security, JWT, OAuth2, Microservices, Kafka, Docker, Kubernetes.

Можно сказать, что Spring практически везде

В блоге JRebel в прошлом году даже вышла статья под заголовком Spring vs. the World: Comparing Spring Boot Alternatives, где сравнивались известные альтернативы герою статьи. Однако все они так или иначе уступают Spring'у, как лидеру рынка.

Инфографика «Most Popular Java Application Frameworks» | JRebel: 2021 Java Developer Productivity Report
Инфографика «Most Popular Java Application Frameworks» | JRebel: 2021 Java Developer Productivity Report

Мы попросили Ильназа Гильязова, Java-разработчика с большим опытом, дать комментарий по этому поводу. Ильназ на основании своего опыта разобрал ключевые плюсы, минусы, проблемы и риски использования Spring, а также возможные альтернативы.

Плюсы

Конечно же, от использования Spring, куча плюсов:

  1. Разработчики, переходящие с проекта на проект используют одну и ту же экосистему.

  2. Новые разработчики, приходящие в команду из других компаний, уже знают Spring*.

  3. Много обучающих материалов (по большей части, начального уровня).

Примечание*: знают ли они его на самом деле – см. в пункте про проблемы.

Приведённые выше пункты не нуждаются в расшифровке — достаточно посмотреть:

  1. Резюме большинства Java-разработчиков.

  2. Большинство вакансий Java-разработчиков.

  3. Состав учебных курсов по Java.

 В общем, это база©

Минусы

Минусы ориентации на Spring также очевидны:

  1. Его целиком (или, по крайней мере, его части) «пихают» и тогда, когда он решает какие-то проблемы, и тогда, когда их только создаёт — кейс со Spring Security о котором пойдет речь ниже.

  2. Некоторых разработчиков впору называть не Java-разработчиками, а Spring Boot разработчиками* – они мыслят только абстракциями Spring'а и в состоянии использовать только те инструменты, которые интегрированы со Spring'ом.

Примечание*: вплоть до так называемых Annotation Monkey

Примеры из опыта:

  1. Достаточно часто необходимо организовать аутентификацию внешнего сервиса в нашем (логин/пароль, сертификат или токен). Для этого, в большинстве случаев, достаточно одного фильтра, который организует всю необходимую функциональность (без завязки на Spring Security), но «Spring-разработчики» упорно следуют шаблону*: если нужна безопасность - подключаем Spring Security, работа с БД — Spring Data JPA, микросервисы – Spring Cloud.

  2. Spring-разработчики, к сожалению, следуют правилам, которых им обучали на вводных курсах, например, использование @Transactional над всеми сервисами, без реального анализа того, что происходит в методах сервиса и нужны ли там реально транзакции. Самый частый негативный пример – генерация большого отчёта аккуратно заставляет все остальные функции сервиса «подождать», т. е. остальные запросы клиентов «подвисают».

Примечание*: конечно же, эта стратегия оправдана, если мы по��имаем перспективы и необходимость расширения (т.е. будем использовать не только 1/100 часть подключаемой библиотеки).

Риски

Тут у Spring достаточно богатая история, к самим ярким примерам котором можно отнести:

  1. Любое решение команды Spring автоматически аффектит ваши сервисы, причём может быть "очень больно".

  2. Нужно закладывать обновление, как минимум, мажорных версий. И это не всегда безболезненно.

Примеры из опыта:

  1. Остановка развития Netflix'овского стека (не по вине Spring Team, но всё же) — многие (мы в их числе), кто строили тогда на этом стеке микросервисы, потом их переписывали).

  2. Deprecate Spring OAuth2 Authorization Server — пришлось уходить на другие решения (например, KeyCloak), хотя некоторые так и остались на Deprecated версии на длительное время*.

  3. Spring 6, который выйдет в этом году требует уже Java 17**.

Примечание*: хотя спустя много лет он возрождается, но всё же.

Примечание**: конечно же, мы приветствуем столь кардинальное решение команды Spring, в перспективе позволяющее в большом количестве проектов переехать на Java.

Проблемы

«Если исполнитель не предупреждает вас о потенциальных проблемах, то вас гарантировано ожидают проблемы».

Наиболее распространенные проблемы:

  1. Первая, как вы могли догадаться, и ключевая проблема заключается в том, что большинство разработчиков на самом деле умеют пользоваться Spring на базовом уровне, но не знают ни устройства Spring Framework, ни уж тем более Spring Boot и других проектов (Data, Security), что приводит к вороху проблем при выходе за привычные простейшие примеры использования. 

  2. Spring Boot'овый (и Cloud) «прибитая гвоздями» интеграции некоторых библиотек значительно затрудняет полноценное их использование.

Несколько примеров из опыта:

  1. Заворачивание тяжёлых операций (расчёт хэша пароля, генерация отчёта) в транзакционные методы — неумение использовать TransactionTemplate, непонимание работы @Transactional для разной формы вызовов.

  2. Выполнение тяжёлых операций в потоках-обработчиках веб-запросов (которых в классической модели ограниченное количество, кроме того, они не предназначены для вызова «тяжёлых» методов).

  3. Отсутствие должной обработки инфраструктурных исключений — как наш сервис обрабатывает обращение клиентов на несуществующий Endpoint? Отвечает ли он нашей DTO или стандартной Spring'овой?

  4. У Spring Boot только недавно появилась официальная интеграция с GraphQL и до сих пор не появилось официальной интеграции с gRPC, который очень любят за рубежом и в проектах со смешением стеков — Java, Go, C#. Приходится «доверяться» неофициальной интеграции, либо писать свою, что потребует навыков, выходящих за рамки «стандартного» набора Spring-разработчика.

Альтернативы

Есть ли альтернативы? Как ни странно, они есть:

  1. Свой стек.

  2. Java/Jakarta EE (Full/Web Profile).

  3. Quarkus/Micronaut/Jakarta MicroProfile.

Свой стек

Свой стек себе могут позволить достаточно крупные компании с серьёзной экспертизой в Java для специализированных решений. Например, именно так поступают коллеги из некоторых крупных банков при построении собственной платформы: меньше слоёв абстракции и common case интеграций — меньше накладных расходов. Конечно же, необходимо учитывать все затраты на подготовку кадров соответствующей квалификации, развитие, поддержку и обновление самой платформы.

При этом тотального «запрета» на использование Spring нет, но есть очень жёсткие ограничения на используемые части и требования к знанию их внутреннего устройства (для обеспечения должного уровня поддержки).

Java/Jakarta EE

Стек Java/Jakarta EE стоит рассматривать в двух сценариях:

  1. Решения на сертифицированный платформах

  2. Зарубежные решения

Решения на сертифицированных платформах — отдельный класс решений, ограниченные требованиями по использованию сертифицированных по требованиям безопасности платформ. Зачастую сертификацию по требованиям безопасности проходят именно Java EE/Jakarta EE совместимые платформы, поэтому инструментарий здесь заранее предопределён и использование сторонних (несертифицированных) библиотек потребует дополнительных издержек на их анализ.

Зарубежные решения чаще (чем в РФ) используют инструментарий Java EE/Jakarta EE на привычных для компаний платформах:

  • WildFly/JBoss EAP

  • WebSphere

  • WebLogic

  • Payara

  • GlassFish

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

Модернизация старых решений

Отдельно стоит отметить проекты по модернизации «старых решений» —  для нас сейчас это наиболее частый кейс, поскольку приложения, разработанные на J2EE/Java EE (написанные от 12 лет назад) морально и в плане безопасности устарели. Например, большие монолиты, написанные на Java EE 6, переводятся на Spring уже 6-ой версии в микросервисной архитектуре с использованием соответствующих шаблонов (1, 2)

Сейчас необходимы специалисты, которые в состоянии плавно переводить (не используя подход "сейчас всё перепишем с нуля") с минимальными простоями переводить всё на современный стек. Естественно, такие специалисты должны разбираться как в Java EE, так и в Spring.

Примечание*: за исключением совсем уж негативных сценариев вроде закрытия проекта Spring или прекращения доступа из РФ к Maven Central, сайтам Spring, но и к ним нужно быть готовыми.

Quarkus/Micronaut/Jakarta MicroProfile

Quarkus/Micronaut/Jakarta Microprofile в России достаточно слабо распространены, но за рубежом  рассматриваются как легковесные альтернативы Spring. Пока мы ��е считаем их сколько бы то ни было значимыми конкурентами, но приглядываться (как минимум, для расширения кругозора) к ним стоит.

Вместо заключения

В ближайшее время вряд ли что-то* сможет «подвинуть» Spring с позиции «самого популярного инструмента», поэтому однозначно стоит вкладывать ресурсы в его изучение, в том числе, достаточно глубокое ознакомление со внутренним устройством и особенностями работы.

При этом стоит не стоит забывать, что основное предназначение Spring — удобная  интеграция и переиспользование существующих решений (как из мира Java/Jakarta EE, так и вне его), поэтому не стоит пренебрегать рассмотрением спецификаций Java/Jakarta EE и «родных» библиотек.

Если хотите «заглянуть под капот» Spring, понять на что он действительно способен, и, наконец, научиться правильно использовать его в контексте нужной задачи, то приглашаем на наш новый курс Spring Framework. На курсе Ильназ рассмотрит под микроскопом ключевые спецификации Java EE/Jakarta EE, сам Spring и различные сценарии его использования, а также много чего интересного, о чем следует знать Java-разработчику. Более подробнее можете ознакомиться на сайте.

Ссылки на инфографику:

  1. Разработка на Java — Инфографика «Экосистема разработки в 2021 году» | JetBrains: Developer Tools for Professionals and Teams

  2. Инфографика «Most Popular Java Application Frameworks» | JRebel: 2021 Java Developer Productivity Report