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

Комментарии (18)


  1. panzerfaust
    11.11.2022 16:20
    +6

    "Минус Спринга в том, что многие пользуются им только на базовом уровне и стреляют себе в ногу время от времени" - вместо Спринга можно вставить любую технологию без потери смысла.

    Реальный минус сегодня, который заложен в самые основы фреймворка, - это жор памяти и ощутимо долгое время старта на больших проектах. С этим бороться реально тяжело. Все остальные "минусы" характерны для любого сколь-нибудь развитого промышленного инструмента.


    1. gkislin
      11.11.2022 17:13

      это жор памяти

      (пусть частичное, но решение - thin jar) : https://dzone.com/articles/spring-boot-thin-jar-builder-for-running-java-micr

      ощутимо долгое время старта на больших проектах

      Spring Native и component index помогают:
      https://stackoverflow.com/questions/47254907/how-can-i-create-a-spring-5-component-index
      https://docs.spring.io/spring-native/docs/current/reference/htmlsingle/
      https://spring.io/blog/2022/09/26/native-support-in-spring-boot-3-0-0-m5


      1. amarkevich
        13.11.2022 00:53

        функционал thin jar реализуется на коленке с использованием maven-dependency-plugin:copy-dependencies + maven-jar-plugin(manifest/mainClass). и решает скорее проблему медленного старта


  1. aol-nnov
    11.11.2022 17:02
    +3

    В ближайшее время вряд ли что-то* сможет «подвинуть»

    автор так увлёкся сносками (которые, лично мне, безумно мешали читать статью), что забыл написать сноску к выводу


  1. Nialpe
    11.11.2022 17:51
    +4

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


    1. aol-nnov
      11.11.2022 19:44
      +3

      Spring плохой или

      spring магический и мало кто заглядывает под капот. на этой благодатной почве зреют как каргокульты (антипаттерны), так и вера в чудо и прочая ересь ))

      На мой не искушенный взгляд, спринг - обширный фреймворк с привкусом энтерпрайза. Он интересный внутри, имеет свои шероховатости, решает многие проблемы и создает некоторые - всё как в среднем по больнице ))


      1. sshikov
        11.11.2022 22:49
        +1

        >spring магический и мало кто заглядывает под капот
        Ну пардон — если кто-то не заглядывает, разве это вина инструмента? Вот я много раз заглядывал, и могу сказать, что это как правило нифига не сложно — исходники спринга конечно не тривиальные, но и ничего непостижимого там тоже нет. А если там и есть такие части — то они чаще всего нам с вами не понадобятся.

        Ну то есть, и эта вот «магия», и то что не все умеют пользоваться — это же явно претензия не к продукту. То есть, если дело в квалификации, то лучше не станет, если спринг заменить чем-то другим.


        1. amarkevich
          13.11.2022 00:55
          +1

          если спринг заменить чем-то другим

          разработчики зачастую о другом и не слышали - ведь любой гвоздь можно закрутить спрингом


  1. dejecher
    11.11.2022 20:44

    Spring не хороший и не плохой - это просто инструмент который можно применять как в подходящих для этого условиях, так и наоборот - в совсем не подходящих

    На мой взгляд Spring не слижком подходит для реализации модной и молодежной микросервисной архитектры. Но тут смотря с чем сравнивать.

    Если к примеру сравнивать с таким фреймворком как quarkus то последний определенно выигрывает и именно по причине того, что изначально ориентирован именно на микросервисную архитектуру (и реализует почти всеcь функционал предлагаемый Spring Boot и в частности все то что мы именуем Opinionated Defaults Configuration). А вот если реализовывать stand alone приложение, или к примеру командно-строчную утилиту, я бы выбрал Spring Boot. Ну по крайней мере у меня сейчас такое мнение


    1. olku
      12.11.2022 10:29

      Согласен. Сам для микросервисов начинаю с Javalin, но интервьюеры кривились почему-то.


      1. dejecher
        13.11.2022 14:51

        для микросервисов начинаю с Javalin, но интервьюеры кривились почему-то

        Возможно отому, что микросервисы это не только, а довольно часто даже не столько RESTFul интерфейс, но и интеграция с другими библиотеками и фреймворками - т.е. именно то, что предлагают Spring Boot и Quarkus

        Но конечно есть и другие точки зрения (и они имеют полное право на свое существование). В частности эти другие точки зрения включают и чмнение о малоценности такого рода интеграции. Еще одна точка зрения говорит о малоценности компиляуии байт-кода в нативные коды - она имеет разные формулировки в.ч. и такую "зачем писать на java чтобы потому компилировать в нативный код - не проще сразу писать на golang?" Я га всякий случай пожчекну - это не мои точки зрения, но я признаю, что они имеют под собой рациональную основу и имеют право на существование (но с моей персональной точки зрения спорны.) При этом я уточняю, что мне в моей работе досточно часто приходится обходиться и без Spring Framework/Quarkus (в том смысле что мне приходится интегрировать другие библиотеки и фреймворки самостоятеьно), равно как и писать код на golang (конкретно микросервисов - для иных целей использовать не приходилось)


  1. AYamangulov
    12.11.2022 12:19
    -1

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


    1. aol-nnov
      12.11.2022 20:35
      +1

      Каким боком мавен централ оказался к этой статье? И, хотелось бы уточнить, это личные фантазии автора или есть какие-то документально подтвержденные прецеденты именно с мавен централом?

      Не гоните, пожалуйста, волну - и так штормит со всех сторон...


  1. kazimir17
    14.11.2022 10:38

    Главная проблема спринга в том, что он просто не нужен, он не решает никаких проблем. Первый раз я познакомился с ним в 2008 году, с тех пор поучаствовал во многих проектах в которых спринг был и в которых нет, так вот я не могу сказать, что хоть как-то ощущал потребность в спринге в проектах где он отсутствовал.


    1. Fuud
      14.11.2022 15:19

      А откуда брались инстансы классов там, где Спринга не было?


  1. noavarice
    14.11.2022 10:38

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

    Суть примеров ясно, но я бы поостерёгся упоминать Spring Security в этом примере. Придумывать свои решения в области безопасности, просто чтобы не пользоваться решением из фреймворком (которое скорее всего протестировано, проревьюено специалистами в области безопасности и т.д.) может быть чревато. Тем более что тот же Spring Security автоматом применяет средства защиты от некоторых уязвимостей (например, в StrictHttpFirewall)


  1. odisseylm
    14.11.2022 10:38

    Статья ни о чем :-( Удивлён, что набрала плюсы, а не минусы. У меня, к сожалению, нет права ставить минус (или плюс).

    Альтернативы в виде jee или самопис имеют похожие или даже точно такие же проблемы.

    Проблема со SpringSecurity не раскрыта - обойтись фильтром можно только в случае сверхпрмитивного приложения/SOA (в моей практике половина сервисов требовала хотя бы пару ролей reader/writer, иногда admin для сброса кешей или получения какой-нибудь статистики). Можно написать свой аналог с кучей кода, но зачем?


    1. dejecher
      14.11.2022 12:21

      Можно написать свой аналог с кучей кода, но зачем?

      ну не всегда этого кода куча. Однако достаточно часто приходится паботать с внешним провайдером услуг аутентификации/авторизации. в этом случае может быть как раз примитивный фильтр. Только не подуматье, что я фанат такого решения. Но если мне за это платят - почему нет?