Почему я ненавижу Spring

Original author: Sam Atkinson
  • Translation
В начале своей карьеры я реально влюбился в Spring. Я так долго ждал его. Я использовал его во всех своих проектах. Вдобавок мне даже удалось впихнуть туда кучу всякой всячины из Spring Integration. Я был кем-то вроде короля XML. Я делал RPC-слой на основе JMS, protobufs и Kaazing для всего нашего отдела и банка в целом. Я думал: «Это так конфигурируемо. Всего-то пара XML-файлов — это действительно гибко». Я был очень доволен собой.

Но некоторые мои коллеги были склонны не согласиться. У них возникали проблемы, когда они пытались связать всё так, как им хочется; они не знали, где какие XML-файлы им нужны. Были проблемы с версиями Spring, с тем, как подружить их (я, к тому же, далеко зашел с модульностью: у нас было 5 или 6 разных модулей с разными номерами версий, и нельзя было просто так взять и понять, какой из них использовать, не спросив меня). Это были тревожные звоночки, но я их не замечал; я думал, что нужно больше документации или что те ребята просто тупые. Такая ситуация типична сама по себе: мольбы пользователей одного из самых нелюбимых и трудных в использовании фреймворков о помощи часто разбиваются о «да там один файл и немного параметров, это не так уж и тяжело», в то время как все остальные целыми днями пытаются найти магическую комбинацию файлов и параметров, чтобы хоть что-нибудь как-нибудь заработало.

Я всё ещё работаю в той же организации, но теперь я пользователь своего старого фреймворка. В результате этого питания кормом своей собаки я стал ненавидеть Сэма (автор имеет в виду себя — прим. пер.) 2009-2010 годов по нескольким причинам, но в основном — за Spring. Spring — это зло в хорошую погоду, но когда его включают в состав библиотеки или API, которым пользуются другие программисты, — это уже другой уровень зла: как плод любви Гитлера и дьявола. Не позволяйте Spring торчать из вашего API наружу.

Spring — отстой по ряду причин, и я почувствовал, что их нужно перечислить, т.к. в google нет четких контраргументов.

  • Конфигурация в XML. Хотел бы я думать, что мы как профессия оставили XML в прошлом. Он невероятно многословен, но это ещё цветочки. Намного важнее то, что я не хочу программировать на XML. Связывание всех классов воедино — чрезвычайно важная часть вашего приложения. Вы Java-разработчик, а не XML-разработчик. Одна из прелестей Java как языка — compile time safety. Я могу скомпилировать свои приложения, в которых нет Spring, и быть на 100% уверенным, что всё собрано, подключено и готово к работе. Но если в приложении есть Spring, ты запускаешь его, ждешь 30-60 секунд, пока оно инициализирует бины, прежде чем упасть. В современном мире это безумие, особенно если это еще и умножается на кучу интеграционных тестов, в которых вам нужно вертеть контейнер так и этак. Отдельного места в расстрельном списке заслуживает «это значит, что я могу менять реализацию без перекомпиляции!». Так никто не делает. Никогда.

  • Магия. Тут обычно следует реплика: «Теперь вы можете делать всё с помощью аннотаций! Больше никакого XML!». Здорово, когда не нужно программировать на XML, но аннотации — это всё ещё магия. Пока вы не запустите приложение, вы понятия не имеете, свяжется ли оно правильно. И даже потом вы не знаете, правильно ли оно связалось; вы всего лишь знаете, что оно связалось. Не люблю магию.

  • Импортирование других Spring-файлов. В данный момент это бесит меня больше всего. Я обнаружил, что существует тенденция разбивать Spring-файлы на более мелкие и раскидывать их по модулям. Я только что убил 2 недели, продираясь сквозь JAR'ы и пытаясь найти правильную комбинацию/порядок/версию Spring-файлов, чтобы кое-что заработало. Spring-файлы в JAR'ах — это плохая, плохая идея. Ужасная. Каждый раз, когда вы размазываете зависимые Spring-файлы по JAR'ам, где-то умирает ребенок.

  • Сложность. Когда на собеседовании спрашиваешь кандидата: «Какие подводные камни есть в Spring?» — чаще всего слышишь в ответ, что у него крутая кривая обучения. Правда это или нет — отдельная тема, но я хотел бы подчеркнуть тот факт, что Spring сейчас настолько сложен, что у него есть собственный фреймворк — Spring Boot. Фреймворк для фреймворка. Мы во «Framework Inception» — фильме о Леонардо Ди Каприо, который пытается найти свой давно потерянный Java-код, всё глубже и глубже погружаясь в слои XML и аннотаций, прежде чем в конце концов покончить с собой.

Штука в том, что я уверен: удачно использовать Spring в приложении теоретически возможно. Я еще никогда такого не видел, и это проблема. Как по мне, все «плюшки», которые он предлагает, вполне возможны и без него. Когда мы спрашиваем о Spring на собеседовании, кандидат обычно отвечает: «Со Spring у вас есть чистый код, разделение ответственности, к тому же он действительно хорош для тестирования». В общем, все те вещи, большим поклонником которых я являюсь (особенно тестирование), но на самом деле это результаты не использования Spring, а хорошего программирования. Возможно, для новичков Spring — это хороший костыль для освоения таких идей, как внедрение зависимостей, mocking и тестирование, но на самом деле они ортогональны Spring. Если вы применяете TDD, у вас в коде не будет геттеров и сеттеров — только внедрение зависимостей через конструкторы, которые вы можете «замокать» для тестирования, а затем, когда вы связываете своё приложение воедино, просто используете часто забываемый способ создания объектов — ключевое слово «new». Зачастую мы создаем класс «ApplicationContext», который отвечает за связывание всего воедино. Он чистый, всё тестируемо, у меня есть compile time safety, и мои тесты выполняются чертовски быстро.
Share post

Comments 262

    +4
    Я только осваиваю Spring, но по смыслу статьи так ине понял чем он плох (я не защищаю и не осуждаю, я просто не понял) Про аннотации в самой же статье сказали, а про магию — ну извините, это инверсия. В любой инверсии вам придется знать ЧТО именно делает каркас к который вы встраиваетесь — это не магия спринга это магия DI.

    А вот кривая обучения — да. Примеры на сайте не промасштабированы, нихрена не понятно с первого взгляда, на каком уровне ты работаешь и что именно за тебя делает магия. Вот тут конечно можно было бы поработать.
      +6
      это не магия спринга это магия DI.

      Посмотрите на Guice — это маленькая библиотека, которая позволяет сделать DI. Но она маленькая, легковесная и в ней много конкретики. Хороший конфиг выглядит как: «для интерфейса Х создай имплементацию Y со всеми зависимостями».
      Хотя тут тоже свои подводные камни для больших проектов.

      В случае со спрингом это Можно сделать так, но редко кто делает — «это сильно много кода». Сервисы и компоненты просто декларируются и закидываются в класспас, а дальше «магия спринга» решит кого куда внедрить и кто кому нужен для работы. Контроля в этом случае нету в принципе.
      Для небольших проектов, где есть по одной имплементации – это вполне удобно. Для крупных — не уверен.
        0
        В таком случае лучше уж Dagger, там конкретный код можно посмотреть.
          0
          А есть примеры использования Dagger за пределами Android? Мне он показалась каким то уж усложненным по конфигурации, по сравнению с Guice.
            0

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


            Мы использовали в десктопщине.


            Если интересует пример — можно посмотреть в github репозитории самого dagger — dagger/examples.

          0
          Для небольших проектов, где есть по одной имплементации – это вполне удобно.


          Кстати, а зачем там вообще DI?

          Вот глобальный вопрос: посмотрите на типичный Spring-проект и ответьте себе честно: там есть польза от DI?
            0
            Если смотреть на те проекты где я работал со spring boot, там есть польза. В проекте 50-100 файлов и все само в кучу собирается. Красиво и удобно, нету тонны кода для ручного создания всего кода.
            ps: но это было удобно только потому, что нужно было получить результат быстро и не париться с веб-фреймворками.

            Если смотреть в целом, то я сам сторонний compile-time связывания, т.е. для меня лучше написать код для создания всех зависимостей.
            Но я прекрасно понимаю, что это огромная гора кода будет. Более того, это будет ужас, если нужно будет добавлять какую-то новую зависимость — это больно.

            У меня нету однозначного мнения на счет DI — это и хорошо и плохо одновременно.
              0
              Нет, польза от DI только в тестах
                0
                О блин, как я мог забыть.
                  0
                  А что, нет? У вас в проекте обычно одна реализация для интерфейса + для теста
                    –1
                    У нас очень и очень редко для теста нужна прям другая реализация. Обычно просто разные значения пропертей.
                      –1

                      Зачем другая реализация в тестах? Там я обычно в контекст моки подкладываю, зачем другая реализация? И интерфейсы тоже непонятно зачем нужны как правило.

                0

                А ещё можно посмотреть на HK2 — оно ещё меньше и проще.

                  0
                  не надо на него смотреть, это древнючий, ужасно написанный контейнер к которому буквально приклеен кусок guice (но не очень аккуратно). смотрите или просто на guice или на чудесный picocontainer
              +12
              Я, кажется, превращаюсь в адвоката Spring, но статья и хорошая, и не очень одновременно.

              Думаю, можно опустить пункты про XML (его ещё кто-то пишет?) и импортирование других файлов, что бы это ни значило. Если речь идёт про размазывание конфигурации по куче jar ов… Ну так и правда делать не нужно :)

              Важный пункт это про магию. И тут надо понимать, что если магию перевести в технический термин «уровни абстракции», то вместо иронично-негативного получим чисто субъективное — нравится подход скрытых абстракций и реализаций или нет. Кто-то хочет написать код руками, чтобы избежать магии, кто-то наоборот, предпочтет добавить понятную ему и документированную аннотацию. Поэтому демонизация Spring из-за его магии — это странно. Spring потому и используют, что он магией скрывает все детали реализации.

              Но очень хороший совет, и его прямо сложно переоценить — это не включение в свои Api / библиотеки зависимости на Spring. Этого и правда нужно избегать, в идеале код библиотеки вообще не должен знать про Spring. В крайнем случае, можно выделить отдельную библиотеку интеграции. Но это ещё Дядюшка Боб завещал, это не особенность конкретно Spring.

              Поэтому отвечая автору «Почему я ненавижу Spring» я бы сказал «Скорее всего, потому что вы не любите уровни абстракции которые не контролируете и предпочитаете им написанный руками boilerplate код».
                –5
                Думаю, можно опустить пункты про XML (его ещё кто-то пишет?)

                Эммм… Да, под Андройд, и еще как) Там это вообще каркас.
                  +5
                  Я имел в виду XML для конфигурации Spring :)
                    0
                    А, ну это другое дело, да) А-то думаю ничего себе товарищ за бортом оказался, ибо то, что под Андройд на нем пишется чуть ли не половина логики, знает даже простой обыватель)
                  0

                  Да пишет (XML) — Егор Бугаенко

                    +1
                    обычно если тащат в приложение спринг, то тащат почти всё (веб, дао, и т.д.) ваше приложение опирается на разномастное, местами старинное дерево абстракций, навязывающих свои интерфейсы, свои, подчас, не самые оптимальные способы работы с core-DI и проч.
                    для поддержки всего этого добра уже мало знать underlying технологии, надо знать интеграционную специфику спринга.
                    авторы многих интеграционных подпроектов одержимы причесыванием всего под одну гребенку, бывает, что суют свои интерфейсы даже если нативные лучше.
                    +3

                    зачем использовать new в тестах, когда есть @MockBean и @SpyBean?


                    и если вас напрягает DI и иже с ним, то как вы выживаете в этом мире микросервисов и распределённых систем?

                      +1
                      Это вопрос автору, переводчику или вообще всем мимо проходящим?
                        0

                        то, что это перевод заметил не сразу. Так что, давайте так:
                        0) вопрос выше — всем мимо проходящим
                        1) вопрос переводчику — зачем такой вброс сюда был? Какую цель вкладывал, когда переводил это?

                          +2
                          то, что это перевод заметил не сразу


                          Вот это, я считаю, самый большой комплимент, который может получить переводчик.

                          вопрос переводчику — зачем такой вброс сюда был? Какую цель вкладывал, когда переводил это?


                          В основном, хотел немного попрактиковаться в переводах :) А конкретно этот пост выбрал потому, меня тоже бесит Spring. Я мог бы еще набросить лично от себя, но холиворить в интернетах надоело :)
                      0
                      Автор, а вы знакомы с проповедями Егора Бугаенко yegor256?

                      http://www.yegor256.com/2014/10/03/di-containers-are-evil.html
                      http://www.yegor256.com/2016/04/12/java-annotations-are-evil.html

                      Выбросил Spring из проекта, остался только JdbcTemplate) Результатом доволен.
                        +3
                        Выбросил Spring из проекта, остался только JdbcTemplate

                        расскажете как вы так сумели?

                          +1
                          ОK, OK, я отказался от DI средствами Spring. Совсем выбросить руки не дошли пока.
                            0
                            Можно еще и Spring JdbcTemplate выкинуть, он не нужен.

                            Что обычно нужно от Spring JdbcTemplate?
                            — подготовить запрос, выполнить и смапить результат на какой-то бин или объект, правильно?

                            Если больше ничего не нужно — у меня есть хорошая новость, чистый JDBC с этим прекрасно справляется!
                            Миниатюрная обертка над бойлерплейт кодом подготовки JDBC запроса (~50-150 строк) и можно не подключать Spring JdbcTemplate в проект.

                            https://docs.oracle.com/javase/7/docs/api/java/sql/PreparedStatement.html#setObject(int,%20java.lang.Object)
                            — этот метод убирает всю сложность подготовки запроса (лучше использовать другой метод, но там немного усложняется код, может +50 строк будет).

                            если интересно, могу закинуть на github мелкий PoC в качестве примера, который я делал не столь давно.

                            ps: конечно, может это зависит от Jdbc драйвера, я тестировал только для PostgeSQL.
                              0
                                0
                                Нет, не нужно, я тоже умею обходиться JDBC.
                                Есть еще http://jdbc.jcabi.com/ от yegor256. Но с ним как-то не срослось под мои нужды.
                                  0
                                  Для работы с базой есть прекрасная библиотека https://commons.apache.org/proper/commons-dbutils/
                                    0

                                    Мне в этом плане очень понравился MyBatis. Особенно когда используется не JdbcTemplate, а какой то ORM типа Hibernate, JPA, spring-data…
                                    Если что то сильно выходит за границы CRUDа — плачешь, колешься пишешь на соответствующем фремворке и думаешь, как было бы проще если бы сам накидывал структуру таблиц и выгребал это все SQLем (а местами так и делаю, через native query)

                                  +1
                                  Автор, а вы знакомы с проповедями Егора Бугаенко yegor256?


                                  ХЗ, спросите у него. Ссылка на его блог — под переводом.
                                  0
                                  Чем мощнее инструмент и чем больше он даёт возможностей, тем легче выстрелить себе в ногу. Так что либо ограничивайте способы применения, либо смиритесь.
                                    +1
                                    С другой стороны, чем мощнее фреймворк и чем больше он дает возможностей, тем он монструознее и тем больше шанс, что 95% его вам нафиг не сдались, и вообще лучше было разбить его на либы.
                                    +2
                                    Мне аннотации нравятся, тестируемость нравится и магия тоже нравится. Но вот когда выясняется, что либа, которая внутри сервера приложений используется для запросов в сеть не может работать через прокси, а в конфигах в ста местах уже прописано «работай зараза» и тебе приходится заменить ее апачевской, которая умеет после нескольких дней выяснения «где же эта сволочь конфиг берет я ведь все указал!?». В общем это да, раздражает. За широкие возможности готовой реализации (магия) приходится платить. Зато сервер разворачивается и работает «сам по себе с парой конфигов».
                                      +5
                                      Одна из прелестей Java как языка — compile time safety.
                                      тут надо тогда не на Spring ругаться, а на весь AspectJ целиком, с включенным режимом инжектирования runtime.

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

                                      В общем ИМХО «не хочу учиться, хочу жениться» какое-то.
                                        0
                                        Совершенно согласен. Я даже подумал, что пока он будет свое ваять, если силенок хватит, он напишет огрызок спринга.
                                          +5
                                          А кто сказал, что он будет «своё ваять»? Возьмет и заюзает тулзу, которая устраивает его больше. Как будто кроме Spring на планете Java ничего нет.
                                          +1
                                          так навалом схожего и попрозрачнее. dropwizard, spotify apollo, lagom, play/slick, etc…
                                          чем больше народ будет уходить на микросервисы, тем сильнее будут отказываться от спринговой монструозности
                                            0
                                            Работал с Play первым и вторым. После него Spring (а конкретно Spring Boot + Spring MVC) — как глоток свежего воздуха.
                                              0
                                              а что именно вас так торкнуло в спринге на фоне плея?
                                                +1
                                                Да много чего на самом деле.
                                                1. В Спринге есть куча проверенного и рабочего функционала как из коробки, так и в виде модулей. В Play же из коробки даже нет DI, это по-моему провал.
                                                2. Если в спринге пытаются держать хоть какое-то backward-compatibility, то в play оно отсутствует как класс. Я помню как наша команда неделю переводила плейовский проект с одной минорной (подчеркиваю — минорной) версии на другую минорную.
                                                3. Вероятность найти на том же стэковерфлове ответ на вопрос в контексте спринга в разы выше. Есть куча статей с примерами. Не плей кроме официальной документации толком негде больше смотреть (а если и есть, то из-за отсутствия backward-compatibility работать на конкретной версии плея оно вряд-ли будет).
                                                4. Все модули прибиты гвоздями. Хочешь вместо плейовского Ebean использовать Hibernate? А вот фиг тебе. Хочешь вместо sbt заюзать gradle или maven — то же самое.
                                                5. Свои конвеншены написания кода. (Например, модельки должны иметь публичные поля).

                                                Ну и еще много чего, сейчас все и не вспомню. Короче, после 2-х лет работы с плей я не вернусь на него ни за какие деньги. По крайней мере в ближайшем будущем.
                                                  +2
                                                  Например, модельки должны иметь публичные поля
                                                  А что в этом плохого?
                                                    0

                                                    согласен — в модели никакой логики не должно быть, потому зачем делать избыточность на доступ к полям через методы?

                                                      0
                                                      На первй взгляд, плохого ничего (хоть и идея достаточно революционная, согласитесь).

                                                      Но, поскольку Play использует Ebean (имплементация JPA), то для Lazy loading JPA должна иметь геттер. И, поскольку в коде его нет, сам плей в момент компиляции будет его генерировать и вставлять в класс, а все участки кода, где используется этот публичный филд, заменит на геттер.
                                                      И вот, дебажите вы свое приложение, в поле у вас значение null (ибо lazy loading), чтобы подтянуть значения из базы вам нужно сделать кол на геттер в дебагерре, но его в сорсах нет.
                                                      0
                                                      это был 1.х Play?
                                                        0
                                                        В основном Play 2.x, хоть и с первым тоже работал.
                                                          0
                                                          это странно, потому что во втором есть DI по-умолчанию, на основе guice
                                                            +1
                                                            Посмотрел документацию. Вы правы.

                                                            Я работал с Play вплоть до версии 2.3.х, и там DI еще не было.
                                                            Guice добавили из коробки начиная с 2.4.x, когда я уже с него ушел.
                                                    0
                                                    Почему всех тянет именно на фреймворки? Попробуйте Akka HTTP что ли для разнообразия.
                                                      0
                                                      Ну так с фреймворками быстрее же (если его знаешь, конечно).
                                                        +1
                                                        Что именно быстрее? Начать проект? Добавить новый endpoint?
                                                        И с какими именно фреймворками?
                                                        И вообще, вы пробовали Akka HTTP?
                                                        +1
                                                        у акка-хттп своя ниша, рест сервисы с гибкими урлами на нем странно делать
                                                  +1
                                                  Пару лет назад осознанно отказался от Spring в одном своем проекте.
                                                  Стал использовать Akka, jooq, dagger.
                                                  За 2 года не пожалел ни разу.
                                                    0
                                                    А чем вы транзакции управляете? JOOQ ведь не умеет
                                                      0
                                                      Упрощенно:
                                                      try {
                                                           dbConnection = getDBConnection();
                                                           dbConnection.setAutoCommit(false);
                                                           new JOOQ(dbConnection).query().execute(); //dbConnection.commit();
                                                      } catch (Exception e) {
                                                          dbConnection.rollback();
                                                      }
                                                      

                                                        0
                                                        Упрощенно, 6 строк, вместо одной, круто.
                                                        А как у вас с уровнями изоляции транзакций?
                                                          0
                                                          Эти 6 строк заворачиваете в обертку и все. Переиспользуете везде. Зато любой джун разберется за 1 минуту и не будет думать как же работает вся эта магия.
                                                            0
                                                            Да какая магия? Создается Proxy класс, т.е. та же самая обертка, и в ней тот же код, почти, как у вас.
                                                            В чем магия?
                                                              +1
                                                              Ну так в том то и дело. Если нет разницы — так зачем платить больше (использовать спринг?)
                                                                0

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

                                                                  0
                                                                  Так без спринга получается меньше. Но да, минимальную инфраструктуру вокруг нужно будет набросать.
                                                                  0
                                                                  В веб приложении часто надо сериализовать/десериализовать json/xml, security, api documentation, интернационализация, миграции,… в Spring это все интегрированно и протестированно, ну а если мы используем Spring то и писать свои обертки не нужно
                                                                    +1
                                                                    Все это точно так же легко решается и без спринга.
                                                                      0
                                                                      Решается, но зачем решать если уже есть готовое?
                                                                        +1
                                                                        Спринг многоцелевой и сложный. Чтобы начать работу со спрингом нужен определенный бекграунд. Любую задачу, которую решает спринг можно решить другими инструментами, которые простые и узконацеленные. Никто не говорит что нужно писать свои велосипеды.
                                                                          0
                                                                          т.е. разобраться с одним спрингом сложнее, чем с полусотней других «простых» решений? В спринге хотя бы всё более менее однообразно и всё работает из коробки, а набор «простых» решений еще придется друг к другу подгонять и писать интеграцию.
                                                                            +1
                                                                            т.е. разобраться с одним спрингом сложнее, чем с полусотней других «простых» решений?


                                                                            Именно. Тут уже внизу писали, что спринг — в топах вопросов на СО.

                                                                            а набор «простых» решений еще придется друг к другу подгонять и писать интеграцию.


                                                                            Наоборот — в виду узкой специализации каждой из библиотек вместе их собрать гораздо легче, чем наконфигурить спринг. Гляньте, например, guice как пример DI. За 1 минуту подключаете и используете во всю.

                                                                            P. S. Если что — я 7 лет использовал спринг. Последние 3 год не использую. Моя продуктивность сильно выросла. Но это мой частный случай.
                                                                              +1
                                                                              Тут уже внизу писали, что спринг — в топах вопросов на СО.
                                                                              возможно это не только в силу его непонятности, но еще и в силу высокой популярности?

                                                                              если я напишу жутко сложную неудобную либу-обертку над JDBC и повешу ее на гитхаб, смогу ли я на основании отсуствия вопросов по ней на СО констатировать ее понятность?
                                                                                0
                                                                                Гляньте, например, guice как пример DI. За 1 минуту подключаете и используете во всю.

                                                                                Вы так говорите, как будто спринговый di подключается дольше.
                                                                        0
                                                                        настройки серилизации спринга, кстати, одно из самых мутных мест. а так люди сами джексон или какой-нибуд gson интегрируют и все.
                                                                        спрингсек — ужасный монстр в котором почти никто не разбирается, тот уровень магии, когда она уже вышла из под контроля (как и многие другие спринговые подпроекты :))
                                                                  0
                                                                  А как у вас с уровнями изоляции транзакций?

                                                                  Я надеюсь вы понимаете, что изоляцию транзакций и сами транзакции управляются исключительно базой данных. А команды для этого посылает jdbc драйвер. Спринг и хибернейт абсолютно ничего нового не делают с транзакциями, всё сводится в конце к jdbc драйверу и методам setTransactionIsolation()/setAutoCommit(false)/commit()/rollback() из java.sql.Connection.
                                                                0
                                                                Руками — написал обертку.
                                                                Выглядит так:
                                                                database.executeAsyncTransactional(create -> create.update...)
                                                                

                                                                Внутри там используется create.transaction
                                                                  0
                                                                  что угодно можно написать самому. Но зачем, если есть готовое, протестированное, удобное в использовании, знакомое другим людям и с советами на со?
                                                                    0
                                                                    А если оно таки неудобное?

                                                                    А если я использую простенькую библиотечку, исходный код которой я могу прочитать за один присест и как угодно пропатчить под себя в случае необходимости, то на кой черт мне SO и другие люди?
                                                                      +1
                                                                      Потому что бэкенд на Akka стартует за 3 секунды и выдерживает 10 000 REST запросов в секунду на моем маке.
                                                                      Приложение на Spring стартует секунд 30, и держит хорошо если 100 запросов в секунду.

                                                                      Приложения примерно сравнимы — простенькие CRUD операции на базе.
                                                                        0
                                                                        Спринг это система интеграции. Если вам нужен перфоманс в ответах, не нужно использовать хибернейт для обращения к базе, а возьмите какое-нибудь другое решение, которое будет для этого предназначено, а не винить поезд за то, что он не летает, это же просто глупо. Более того можно без проблем прикруть акку к спрингу. Еще раз: спринг это система интеграции. Его сила в возможности быстро и удобно интегрировать какие-то решения или использовать готовые интеграции из коробки. Если интегрировать нечего, а надо отвечать быстро на простые запросы, то вероятно, что спринг просто не нужен. И да, было бы интересно взглянуть на тесты и их результаты, на которые вы ссылаетесь в своем комментарии.
                                                                          +1
                                                                          Можно посмотреть на приложение на Spring?
                                                                            0
                                                                            Если вы имеете ввиду веб-приложение с реактором, то можно посмотреть на примеры из бута.
                                                                              –1
                                                                              Хочу посмотреть на приложение на Spring которое стартует секунд 30
                                                                                0
                                                                                Да, прошу прощения, я не туда ответил. Мне тоже интересно, что это за приложение такое и почему оно 30 секунд стартует. Уверен, что спринг тут играет очень косвенную роль. Например включено сканирование всех 100500 классов проекта и зависимостей. Или кучу времени инциализируется хибернейт и тд…
                                                                  +1
                                                                  Как по мне, все «плюшки», которые он предлагает, вполне возможны и без него.

                                                                  С этих слов обычно начинается эпичное велосипедостроение. Насколько велосипедостроение хорошо или плохо — тема для отдельного холивара.
                                                                    +1
                                                                    А еще эти слова внезапно могут значить, что автор нашел нормальный способ делать то же самое без Spring и велосипедов (другой способ DI, например).
                                                                      +3
                                                                      другой способ DI

                                                                      обычно в таком случае человек рассказывает об альтернативе и какие плюсы он получил от перехода с инструмента А на инструмент Б. Если же человек говорит "возможны и без него" не приводя примеров, то это начинает попахивать

                                                                    +11

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

                                                                      +4
                                                                      Полностью согласен, отдельно стоит упомянуть что при гуглении методов решения какой-то проблемы/задачи первыми вылезают наиболее «проверенные временем» варианты, т.е. те что были опубликованы раньше, и отдельной проблемой становится узнать «а надо ли еще вот это вот все писать/реализовывать» или в современных реалиях уже все что нужно это какая-нибудь аннотация на классе/jar в класспасе и все сработает само
                                                                        0
                                                                        Особый кайф ловишь, когда эти «проверенные временем» варианты на XML, а у тебя в проекте — нет, и конверсия не всегда тривиальна.
                                                                      +8
                                                                      Есть пачка бонусов которые перевешивают:
                                                                      1. огромное количество библиотек и реализаций.
                                                                      Попробуйте навелосипедить свой spring-security c каким-нибудь oauth собственнм сервером и клиентом. Куча багов и без гарантий что дырок нет. Альтернативу @Transactional с нетривиальнм двухфазным коммитом (например БД + Очередь в единой транзакции). Возможно вы напишете свое, но сколько это займет времени. Возможно вы найдете для всего альтернативы, но опять же время на изучение и не меньшее время чтобы все это подружить между собой.
                                                                      2. сообщество.
                                                                      Легко найти того, кто знает, делал и есть доки, SO и т.д. Представьте, что у вас ушел 1-2 ключевых разработчика, кто делал ваши велосипеды и потом найдите и пофиксите сложный баг.
                                                                      3. оттестированно.
                                                                      Куча проблем за вас решена, причем проблемы в основном транспортного уровня, безопасность и т.п. Туча народу пробежала по граблям и убрала большинство.
                                                                      4. относительно быстрый старт.
                                                                      Сделать достаточно сложный проект на spring-boot для быстрого старта как прототип относительно несложно по количеству кода и времени. Самостоятельные попытки найти нужные библиотеки и связать их вместе только для того чтобы быстро показать и выбросить/поменять намного труднее.
                                                                        +7
                                                                        1. огромное количество библиотек и реализаций. Попробуйте навелосипедить свой spring-security c каким-нибудь oauth собственнм сервером и клиентом.

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


                                                                        Альтернативу @Transactional с нетривиальнм двухфазным коммитом (например БД + Очередь в единой транзакции).

                                                                        Двухфазный коммит делает не Spring, а стороннияя библиотека-координатор, например Atomikos, Narayana, etc. Spring @Transactional делает лишь наивный автоматический прокси на коммит/роллбэк, который также легко сделать вручную при помощи java.lang.reflect.Proxy, AspectJ или ByteBuddy. В реальных проектах практически всегда требуется вручную контролировать сбои и взависимости от типа ошибки нужно помимо роллбека повторить транзакцию, реинициализировать ресурс, отрапортовать о сбое, собрать метрики… Вот вам и свой @Transactional. Кроме того есть мнение, что XA вообще не рекомендуется использовать...


                                                                        но опять же время на изучение и не меньшее время чтобы все это подружить между собой

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


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

                                                                        Ваши 1-2 разработчика писали когда-нибудь bean postprocessors? Скорей всего они намолотили кучу кривой прикладной магии ввиде специфических @Заклинаний. Разобраться почему не проксируется бин, кто его процессит и в какой последовательности и почему вдруг что-то перестало работать — никто не будет. Девелоперы как правило понавтыкают костылей, чтобы хоть как-то решить требуемую задачу.


                                                                        Куча проблем за вас решена

                                                                        И на ровном месте создана другая куча. Если все так просто — почему на SO Spring держится в топе? Как правило всегда есть более простое и элегантное решение каждой конкретной проблемы. Spring же пытается влезть без вазелина везде, где это только возможно, вцелом значительно усложняя архитектуру и упрощая лишь какие-то конкретные простые случаи использования. Кроме того, подобное упрощение имеет негативный эффект: куча кодеров, не понимая принципы работы, начинает копипейстить туториалы и SO, допуская архитектурные ошибки. И, столкнувшись с проблемами или с незнанием того, как что-то конкретное сделать на спринге, начинают грязно костылить.


                                                                        Сделать достаточно сложный проект на spring-boot для быстрого старта как прототип относительно несложно

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

                                                                          –2

                                                                          А как прекрасно становится, когда надо оверрайдить версии библиотек, прибитых гвоздём в parent pom'е spring boot.


                                                                          Например, если нужна определенная версия jetty-client с её зависимостями; у тебя уже есть нужный bom, но его не подключишь, т.к. parent pom оверрайдит.

                                                                            +2

                                                                            а мне казалось, что чтобы заменить версию библиотеки, достаточно просто в своём pom-файле в properties переопределить для зависимости на новую версию...


                                                                            <properties>
                                                                              <jetty.version>9.4.2.v20170220</jetty.version>
                                                                            </properties>

                                                                            имена нужных переменных берутся тут поиском по необходимому артефакту

                                                                              0

                                                                              Похоже вы правы, если mvn dependency:tree -Dverbose=true меня не обманывает.


                                                                              Скорее всего, кусок pom'а вида


                                                                                <properties>
                                                                                  <java.version>1.8</java.version>
                                                                              
                                                                                  <jetty.version>9.3.20.v20170531</jetty.version>
                                                                                </properties>
                                                                              
                                                                                <dependencyManagement>
                                                                                  <dependencies>
                                                                                    <dependency>
                                                                                      <groupId>org.eclipse.jetty</groupId>
                                                                                      <artifactId>jetty-client</artifactId>
                                                                                      <version>${jetty.version}</version>
                                                                                    </dependency>
                                                                                    <dependency>
                                                                                      <groupId>org.eclipse.jetty</groupId>
                                                                                      <artifactId>jetty-http</artifactId>
                                                                                      <version>${jetty.version}</version>
                                                                                    </dependency>
                                                                                    <dependency>
                                                                                      <groupId>org.eclipse.jetty</groupId>
                                                                                      <artifactId>jetty-io</artifactId>
                                                                                      <version>${jetty.version}</version>
                                                                                    </dependency>

                                                                              у меня появился неспроста. Возможно, зависит от версии мавена и на 3.5.0 просто не проявляется. IIRC, они несколько раз переделывали resolve зависимостей в третьей ветке.

                                                                            0
                                                                            О боже, вы только что перечислили всё то, что было у меня в голове все эти годы! Я чувствовал, что со Spring много чего не так, но чтобы вот так взять и выразить словами… Да вам надо статью пилить!
                                                                              +3

                                                                              Хм. Ну вот так-то передергивать не нужно:


                                                                              например тот же Servlet уже содержит простые средства security.

                                                                              Вам про OAuth, а вы про сервлеты. Покажете, в каком месте у сервлетов OAuth? :)


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

                                                                                +2
                                                                                Большинство джунов не в состоянии не только написать такой, но и понять зачастую. Поэтому посты типа "я ненавижу..." следует читать с солидной долей скепсиса.

                                                                                Это понятно. С другой точки зрения, джун, который мало-мальски в состоянии распарсить файл и запихнуть его в базу данных, при попытке сделать это на Spring Batch наполняется лютой и праведной ненавистью.

                                                                              0
                                                                              свой spring-security c каким-нибудь oauth

                                                                              в мавен-репозитории значатся как минимум Apache Shiro и PicketBox Assembly, если искать в категории "Security Frameworks". Применительно к OAuth2, сервера и клиенты ищутся в гугле достаточно легко, и Spring там далеко не на первом месте.

                                                                              +2
                                                                              Эх… когда же всё таки появится что-то похожее на Flask для джавы?
                                                                                0

                                                                                Spark не устроит?

                                                                                  0
                                                                                  Близко, но не оно. А какие есть ещё альтернативы?
                                                                                  0
                                                                                  ну можете глянуть на ratpack.io… у меня с ним положительный опыт в проекте (чистый API, UI отдельное SPA на JavaScript)
                                                                                  +1
                                                                                  Использовал Spring, исключительно с полным описанием всех компонентов через XML и без всяких Autowired, могу сказать, что получается очень удобно. Во-первых никакой магии, всё описано в XML до последнего параметра. Во-вторых можно без перекомпиляции менять кучу всего и это, вопреки мнению автора статьи, действительно используется. В-третьих я никогда не пойму ненависть по отношению к XML, по-мне это чудесный формат и пока никому ещё не удалось создать что-то лучше, единственный его недостаток это то, что там нет синтаксиса для массивов, поэтому при маппинге возникают неоднозначные ситуации (но XML Schema это решает).
                                                                                    +2
                                                                                    Тоже не понимаю ненависти к XML.
                                                                                    Многословен? А вы куда-то все время торопитесь? :)

                                                                                    Зачастую очень многих проблем с «многословностью» можно избежать если почитать стандарт + сопутствующие технологии (например namespaces)
                                                                                      0
                                                                                      Абсолютно идентично можно всё описать в джава-конфиге, только с проверкой типов во время компиляции. Мне так даже больше нравится.
                                                                                    +1
                                                                                    Вброшу свои пару мыслей на вентилятор:
                                                                                    1. Любой фреймворк создается для решения какого-то определенного множества задач. Если ваша задача не входит в рамки фреймворка, то это проблема не фреймворка, а вашего выбора.
                                                                                    2. Использовать какой-то фреймворк или не использовать, это как выбор религии — никто не в праве навязывать вам выбор и никто не в праве порицать ваш выбор.
                                                                                      0
                                                                                      Любой фреймворк создается для решения какого-то определенного множества задач.


                                                                                      И в этом большая проблема самого подхода «фреймворк». Эй, люди, как насчет SRP? Хороший инструмент должен решать одну задачу. Помню, когда я только начинал осваивать Spring, я не мог понять, какую задачу решает он. После раскуривания манов у меня сложилось ощущение, что он пытается решить вообще все задачи. Так оно и оказалось. Это оборачивается тем, что потом вы начинаете думать, как подружить Spring с библиотекой/фреймворком X. Это ж звездец какой-то! Я программист, а не семейный психолог. Я хочу писать свой код, а не сглаживать межфреймворковые противоречия. Не припомню, чтобы мне приходилось даже думать о том, чтобы подружить две библиотеки. Одну ты вызываешь, когда нужно А, другую — Б.
                                                                                        0
                                                                                        Спринг сам по себе решает ровно одну задачу. Интеграцию решений. Плюс у спринга еще есть много дополнительных библиотек, которые решают другие задачи. Тоже обычно по одному за раз.
                                                                                          0
                                                                                          Спринг сам по себе решает ровно одну задачу. Интеграцию решений.


                                                                                          Интеграция решений — это работа программиста.
                                                                                            0
                                                                                            Ну вот заинтегрировал я 3 библиотеки, что, мне за это заплатят деньги?
                                                                                              0
                                                                                              Не знаю как Вам, а мне платят. А что такое программирование если не интеграция решений? Работа программиста в том и заключается, чтобы выдать продукт А, используя инструменты B, C и D. Ну это если не брать всяких мышевозов с джумлой.
                                                                                                0
                                                                                                Работа программиста — это решать задачи с использованием программирования.
                                                                                                Т.е. вам платят за программирование, не за решение задач?
                                                                                                  0
                                                                                                  Ну дык это никак не противоречит тому, что я сказал
                                                                                              0
                                                                                              Ну да, а так как я очень ленив, я люблю, когда за меня эту работу делает готовый фреймворк. Я как программист всегда думаю о том как автоматизировать любую деятельность, почему же интеграцию обязательно нужно делать руками?
                                                                                                +1
                                                                                                Да просто потому, что зачастую руками сделаешь проще и понятнее, и поддерживать будет проще.

                                                                                                Есть easy, a есть simple. Easy — это когда написал пару строчек. Simple — это когда легко разобраться, как это работает, и просто изменить что-то в одном месте, будучи уверенным, что ничего не сломалось где-нибудь еще.

                                                                                                Spring — это easy (пока не нужно сделать шаг влево/вправо :)), но это очень, очень далеко от simple. И вот этот not simple оборачивается hard, когда нужно сделать тот самый шаг в сторону.

                                                                                                Вообще каждый выбирает сам. Я начинал с предпочтения easy, меньшего объема кода, минимального дублирования и т.д. Сейчас предпочитаю немного отойти от easy, чтобы сделать simple.
                                                                                                  0
                                                                                                  Очень люблю писать велосипеды, но с опытом приходит понимание, что обычно лучше использовать готовое решение, особенно если оно знакомо другим разработчикам и решает все твои задачи. А велосипеды требуют не меньшей работы, чем разобраться со спрингом хотя бы из за того, что для всех его частей придется писать тесты, а потом еще ловить баги, проблемы секьюрити, корнер-кейзы и тд. Да еще если кто-то после тебя на твои велосипеды придет, то будет материть тебя на чем свет стоит (а то и решит, что её нужно переписать), потому что спринг знаком более-менее каждому современному джава-разработчику, и имеет очень неплохой уровень качества — как кода и архитектуры, так и проработанности деталей и покрытия тестами, а ваш велик придется исследовать с нуля, неизвестно какого он качества, да и не был бы я уверен, что по ходу развития системы сложность вашей собственной интеграции не станет существенно выше её же в спринге.
                                                                                                    0
                                                                                                    Очень люблю писать велосипеды, но с опытом приходит понимание, что обычно лучше использовать готовое решение, особенно если оно знакомо другим разработчикам и решает все твои задачи.


                                                                                                    А у меня с опытом приходит понимание, что готовые решения — это не однозначное добро, особенно когда к этому готовому решению городить столько костылей, что объем костыльного кода начинает превышать объем самого «решения». А еще с опытом уходит страх перед чужими «технологиями», которые при ближайшем рассмотрении оказываются теми же велосипедами.

                                                                                                    ваш велик придется исследовать с нуля


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

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


                                                                                                    Ну так не уверен — не берись, уверен — делай и никого не слушай. «Главное понимать что ты хочешь и что можешь.» (https://habrahabr.ru/post/259831/#comment_8453133)
                                                                                                      +2
                                                                                                      готовые решения — это не однозначное добро

                                                                                                      я никогда не говорил, что готовые решения это однозначное добро. Только конкретно о спринге и с большими оговорками на то, что не стоит воспринимать спринг как универсальное решение для всех и вся и рассчитывать, что там нет проблем или решены любые ваше потребности. Это готовое решение по интеграции, которое часто при прочих равных на мой взгляд выигрывает перед самописным решением, когда речь идет о проекте, которые будет развиваться и разрабатываться не одним человеком. Во многом из за большого числа уже готовых интеграций, которые не без греха, чего уж, но работают без необходимости всё это писать самому.
                                                                                                      особенно когда к этому готовому решению городить столько костылей, что объем костыльного кода начинает превышать объем самого «решения»

                                                                                                      Да, спринг часто кастомизируют, тем он и ценен, но вот так, чтобы объем кода кастомизации превышал объем бизнес-кода… такого я еще не видал. Да еще и весь костыльный, точно ли тут дело в спринге?
                                                                                                      Простите, но в ваших комментах сквозит нечто вроде детского страха перед тем, что сделали «взрослые дядьки»: мол, они могут сделать хорошо, потому что взрослые,

                                                                                                      Я давно не меряюсь размером со «взрослыми дядьками», с опытом просто приходит понимание, что если ты хочешь сделать продукт, то нужно принимать решения, которые будут позитивны для продукта и его развития в существующих условиях, а не для тебя конкретно. Да, спринг мне нравится, но так же мне нравится например котлин, но я не тащу его в каждый большой проект, потому что кроме меня на этом проекте есть и другие люди и некоторые ожидания бизнеса, так что пишу на котлине в свободное от работы время. Хотя котлин сам по себе намного эффективнее джавы, но знакомость для разработчиков бывает важнее, если в проекте участвует больше трех человек и проект развивается.
                                                                                                      Ну так не уверен — не берись, уверен — делай и никого не слушай. «Главное понимать что ты хочешь и что можешь.»

                                                                                                      Управление сложностью большой программной системы дело не простое, а прогнозировать такое управление на будущее и подавно. Поэтому уверенным в таком вопросе быть никак нельзя, тут приходится решать вопросы по мере их поступления. В какой-то мере и в этом спринг лучше самописного решения, потому что он долгие годы собирает типовые решения типовых проблем, которые можно если не использовать из коробки, то по крайней мере в разумное время приспособить под свои нужды.
                                                                                                        0
                                                                                                        Вот вы в целом пишете правильные вещи, и всё-таки смотрите на спринг как на нечто божественное, что вам не дано понять, повторить или обойтись без этого. Годы собирания типовых решений типовых проблем — это, конечно, показатель, но тоже спорный. Во-первых, Spring — вещь общая, и вполне возможно, что собственное решение будет проще и лучше (в том числе — на long term). Во-вторых, что если многие из этих «решений» на самом деле решают проблемы, которые породил сам Spring.

                                                                                                        Кстати, вы часто говорите, что Spring — это решение для интеграции. Можете привести пример, когда что-то с чем-то не спринговое нужно интегрировать, это действительно проблема и Spring ее решает?
                                                                                                          0
                                                                                                          Во-первых, Spring — вещь общая, и вполне возможно, что собственное решение будет проще и лучше (в том числе — на long term).

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

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

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


                                                                                                            Ясно, спасибо, я думал, вы имеете в виду что-то другое.
                                                                                                              0
                                                                                                              Что например? Может показаться, что мелочи, но на мой взгляд совсем нет, да и не так иллюзорно это, когда спринг из коробки поднимает стек нетфликса, например.
                                                                                                                0
                                                                                                                Я просто думал, что вы говорите о какой-то интеграции, о которой я не знал / забыл.
                                                                                                                  0
                                                                                                                  вмешаюсь немного в ваш диалог. Мне кажется (возможно я ошибаюсь) что под интеграциями обычно (если не оговорено иное) подразумевают что то типа круга задач решаемых например Apache Camel.
                                                                                                                    0
                                                                                                                    кто-то интегрирует системы, а кто-то библиотеки в системе, всем нужны свои инструменты
                                                                                                                –1
                                                                                                                Приведите топ 10 проблем, которые создал спринг, которые он сам же и решает.


                                                                                                                Я не готов сейчас дискутировать на эту тему. Тем более, что вы сами понимаете, что они есть.
                                                                                            +2
                                                                                            На самом деле автор статьи достаточно прав. Используя спринг на проекте — вы все больше и больше пишите кода, не связанного с проектом, но связанный со спрингом. В некотором смысле, спринг обязывает вас говнокодить. Код должен содержать бизнес логику, а не фабрики, интерфейсы, конверторы, дто и т д. В этом и есть «болезнь» джавы, потому что когда-то давно «умные» дяди придумали кучу стандартов под маркой Java EE, и все фреймворки начали под него подстраиваться. Ребят, задайте вопрос, «что делает спринг у меня на проекте»? Делает DI? А сколько у вас реализаций на интерфейс? Одна?? Так какой это нахрен DI? То есть вы юзаете спринг для того что бы создать ОДИН СРАНЫЙ СИНГЛТОН? Рилли??? Service/@Repository/@Controller и для этого всего-то спринг??? Так может вы просто не знаете как писать тестируемый код с синглтонами? Так почитайте! Опять таки. Спринг, даже со своей гибкостью кривой! И не покрывает некоторые простейшкие случаи! К примеру Spring-Data-Jpa. Простейший кейс. Почему нельзя было добавить слово limit в синтаксис spring-data??? Почему когда дело доходит до более-менее сложных операций (а не CRUD) постоянно приходится отходить от «идеалов» спринга, и постоянно что-то дописывать? Ребят, если вы говорите что спринг мега-крутой и хороший фреймвок, скорее всего вы просто не пробовали что-либо другое. Попробуйте пописать годик-два проект например на Play Framework-е, желательно на старом, что бы без DI. Попробуйте Vert.X с его реактивным программированием. Или попробуйте сами построить нужную вам архитектуру на простом веб-сервере, без сервлетов вообще. Попробуйте писать код БЕЗ JPA, продумайте архитектуру и тогда вы начнете мыслить по другом. А то у нас бл*ть не программист, а Senior Spring-Framework Developer, и если что-то не входит в спринг, не в силах решить проблему. А самое интересное, что отказавшись от спринга, вы хоть и напишите «маленький» велосипед в виде кастомной архитектуры. НО! Вы увидите, что ваш код стал намного чище и намного гибче, чем со спрингом. И вы имеет ПОЛНЫЙ контроль над своим кодом! Я пишу на джаве с 2010 года, за это время были совершенно разные проекты с соершенно разными подходами. И к огромному сожалению, я заметил, что мода «богатых дядек» на ентерпрайз только усугубляет вещи в джаве. «Типичные вещи» в джаве можно делать намного проще, чем вы можете себе представить. (PHP программисты наверное офигивают, когда видят, как на джаве пишутся веб приложения, потому что у них нету джава ЕЕ, спринга и т.д., и там всё гораздо чище и проще).
                                                                                              0
                                                                                              Так может вы просто не знаете как писать тестируемый код с синглтонами? Так почитайте!

                                                                                              дайте ссылки что ли
                                                                                                +2
                                                                                                Как и любой другой код. Тем же JUnit + Mockito или powermock. Если вы будете писать код в стиле спринга — а именно, сохранять ссылки на синглтон в полях класса — не будет никаких проблем с тем что бы их замокать. + никто не запрещает вам, делать конструктор синглтона не приватным, а пекедж-протектеж, что бы Ваши моки могли без проблемно мокать. Кроме того, end-to-end/интегрейшн тесты никто не отменял. Да и уровень покрытия с ними намного лучше, чем с юнитами. + Автотесты от QA. Не вижу никаких проблем.
                                                                                                  –1
                                                                                                  Если вы будете писать код в стиле спринга — а именно, сохранять ссылки на синглтон в полях класса — не будет никаких проблем с тем что бы их замокать.

                                                                                                  Зачем сохранять ссылки на синглтон в полях класса, если это синглтоны? Их же можно вызвать прямо там где нужно.

                                                                                                  Есть класс EmailSender если я в тесте забуду замокать все методы, а могут быть и новые методы, которые нало не забыть замокать, может получится так что этот сервис отправит письмо в тесте, что естественно не допустимо

                                                                                                  Да и уровень покрытия с ними намного лучше, чем с юнитами.

                                                                                                  Но они медленные
                                                                                                    0
                                                                                                    Есть класс EmailSender если я в тесте забуду замокать все методы

                                                                                                    замокайте весь класс сразу в тесте через тот же PowerMockito.mockStatic и возвращайте реальные вызовы уже для конкретных методов в этом классе. Заодно будете уверены, что у вас вызываются ровно те методы, которые вы планировали тестировать

                                                                                                      0
                                                                                                      Зачем сохранять ссылки на синглтон в полях класса, если это синглтоны? Их же можно вызвать прямо там где нужно.

                                                                                                      Чтобы ограничить разрастание макарон в коде.

                                                                                                      0
                                                                                                      сохранять ссылки на синглтон в полях класса — не будет никаких проблем с тем что бы их замокать

                                                                                                      Инстанс вы в конструкторе получаете или ининциализируете поле?
                                                                                                      private EmailSender emailSender = EmailSender.getInstance();
                                                                                                      
                                                                                                        0
                                                                                                        Инициализирую прямо в поле. Конструкторами — тоже хорошая практика. Главное что бы было удобно, и понятно, каждый выбирает как ему удобнее. С конструкторами мне не очень нравится, потому что иногда синглтонов может быть много, и тогда конструктор становится большим и принимать много параметров, и это становится не удобным и не красивым кодом.
                                                                                                          0
                                                                                                          Конструкторы лучше. Так как легче тестить. Например, когда нужно замокать этот самый EmailSender. Но да, бывает, что конструктор очень сильно ростет. Я в таких случаях создаю объект Holder который содержит ссылки на все синглтоны.
                                                                                                            0
                                                                                                            Т.е. Вы сами создаете инстансы классов и передаете синглетоны? А если завтра надо будет использовать SmsSender вместо EmailSender, Вы перепишите весь код?
                                                                                                              0
                                                                                                              Т.е. Вы сами создаете инстансы классов и передаете синглетоны?


                                                                                                              Да. Вот пример. В нем как раз есть и имейл сендер и смс сендер и пуш сендер =).

                                                                                                              А если завтра надо будет использовать SmsSender вместо EmailSender


                                                                                                              Любая IDE это делает через 2 клика.
                                                                                                                0
                                                                                                                Любая IDE это делает через 2 клика.

                                                                                                                А как же принцип открытости/закрытости?
                                                                                                                  0
                                                                                                                  И как код выше противоречит этому принципу?
                                                                                                                    –1
                                                                                                                    закрыты для изменения: в результате расширения поведения сущности, не должны вноситься изменения в код, который эти сущности использует.

                                                                                                                    Вы не только добавляете новые сущности но и вносите изменения в код.
                                                                                                                      –1
                                                                                                                      Так смс это не расширение, а новое поведение, поэтому все честно.
                                                                                                                        –1
                                                                                                                        А что тогда расширение?
                                                                                                                          0
                                                                                                                          Добавить в смс враппер еще один метод.
                                                                                                                            0

                                                                                                                            И это не будет новым поведением? От этого же могут изменится результаты

                                                                                                            0
                                                                                                            Инициализирую прямо в поле.

                                                                                                            А если завтра надо будет использовать SmsSender вместо EmailSender, Вы перепишите весь код?
                                                                                                              +2
                                                                                                              class SmsSender implements ISender{...}
                                                                                                              class EmailSender implements ISender{...}
                                                                                                              
                                                                                                              public class Sender{
                                                                                                                private static final ISender smsSender = SmsSender.getInstance();
                                                                                                                private static final ISender emailSender = EmailSender.getInstance();
                                                                                                              
                                                                                                                public static ISender getInstance(){
                                                                                                                  return condition ?  smsSender : emailSender;
                                                                                                                }
                                                                                                              ....
                                                                                                              }
                                                                                                              


                                                                                                              Не знаю как у вас, у меня ни разу не было случая, что бы это «когда-то» наступило. Закладывать в основу кода, то, что когда-то что-то может изменится, зачастую есть ошибочным, ибо это когда-то никогда не наступит. Но, конечно случаи бывают.
                                                                                                                +1
                                                                                                                Опять же, ребят, я не пытаюсь вас убедить в том, что спринг полное говно и его нужно избегать. Нет. Я просто хочу донести до вас то, что жизнь без спринга существует, и иногда это даже намного лучше чем с ним. Конечно, всё очень индивидуально. Но! Просто перед тем как начинить новый проект, надо задать себе 3 вопроса:
                                                                                                                1. Что будет делать у меня на проекте спринг.
                                                                                                                2. Все ли сложные случаи он покроет, или надо будет писать костыли для него же.
                                                                                                                3. Какая есть альтернатива для решения этих задач.
                                                                                                                Посмотреть на эти альтернативы, возможно они намного лучше подойдут вам чем тот-же спринг.
                                                                                                                  +1
                                                                                                                  Вот это и есть DI, это и делает Spring :)
                                                                                                                  Sender у вас какбы контекст из Spring.
                                                                                                                    +1
                                                                                                                    Уж лучше я в коде проверю кондишн и обращусь к нужной реализации, чем буду цеплять для этого спринг. Тем более что кондишены для получения реализации в рантайме там насколько ужасно и не очевидно сделаны, что приходится каждому новому разработчику объяснять как оно работает. А если это одноразовое изменение — это вообще не проблема. И ничего не надо переписывать, максимум — пару строчек кода. Да и за всё время таких случаев почти не было.
                                                                                                                      +1

                                                                                                                      но то DI от Spring, который какой-то магический, а тут свой, родной и понятный

                                                                                                                        0
                                                                                                                        Если у вас есть реальная потребность в DI — есть много других библиотек, которые нормально справляются с этой задачей. Тот же Google Guice.
                                                                                                                    0
                                                                                                                    С конструкторами мне не очень нравится, потому что иногда синглтонов может быть много, и тогда конструктор становится большим и принимать много параметров, и это становится не удобным и не красивым кодом.

                                                                                                                    Тут как бы звоночек о том, что надо подумать над архитектурой класса, т.к. он стал брать на себя слишком много. Но не всегда, конечно, можно/нужно разбивать класс на несколько. Тогда может прийти на помощь Lombok, если все поля — инжекты бинов. Будет что-то вроде:
                                                                                                                    @Service
                                                                                                                    @AllArgsConstructor
                                                                                                                    public class MyFatService {
                                                                                                                        private final SomeRepository someRepository;
                                                                                                                        private final SomeBean2 someBean1;
                                                                                                                    	...
                                                                                                                        private final SomeBean10 someBean10;
                                                                                                                    	
                                                                                                                        // Дальше код
                                                                                                                    }
                                                                                                                    

                                                                                                                    В этом случае никаких @Autowired и никаких конструкторов не нужно.
                                                                                                              0
                                                                                                              Для Play или Vert.x есть модуль который генерирует Swagger документацию только добавлением зависимости в pom?

                                                                                                              SpringFox
                                                                                                                0
                                                                                                                Для начала — да есть. Но даже если бы и не было — это не должно быть чем-то страшным. Всё что делает сваггер — принимает JSON с описанием. Никакой магии он не делает, и я не вижу никаких проблем реализовать это в течении одного дня.
                                                                                                                https://swagger.io/playing-with-swagger-using-swagger-and-swagger-ui-with-the-play-framework/
                                                                                                                  0
                                                                                                                  https://swagger.io/playing-with-swagger-using-swagger-and-swagger-ui-with-the-play-framework/

                                                                                                                  Это не совсем
                                                                                                                  модуль который генерирует Swagger документацию только добавлением зависимости в pom


                                                                                                                  Spring без Swagger
                                                                                                                  @Controller
                                                                                                                  public class MyController {
                                                                                                                  
                                                                                                                      @RequestMapping(value = "test")
                                                                                                                      public  @ResponseBody String save(@RequestBody  Animal animal) {
                                                                                                                          System.out.println(animal.getClass());
                                                                                                                          return success;
                                                                                                                      }
                                                                                                                  }
                                                                                                                  


                                                                                                                  Добавляем зависимости
                                                                                                                  compile group: 'io.springfox', name: 'springfox-swagger2', version: '2.7.0'
                                                                                                                  compile group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.7.0'

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

                                                                                                                  В Play
                                                                                                                  @ApiOperation(value = "get All Todos",
                                                                                                                       notes = "Returns List of all Todos",
                                                                                                                       response = Todo.class, 
                                                                                                                       httpMethod = "GET") 
                                                                                                                  public static Result getAllTodos() { 
                                                                                                                       return ok(toJson(models.Todo.findByUser(SecurityController.getUser()))); 
                                                                                                                  }
                                                                                                                  

                                                                                                                  А что если мы в методе поменяем тип а в ApiOperation забудем, компилятор ведь не может это проверить, в SpringFox оно само выводится

                                                                                                                +2
                                                                                                                Почему нельзя было добавить слово limit в синтаксис spring-data???
                                                                                                                Добавьте Pageable/PageRequest к методу, он генерирует LIMIT;
                                                                                                                  –2
                                                                                                                  Да, я знаю о этом. Но это уже выглядит криво, не правда ли? Если есть такой крутой механизм, в чем была сложность добавить что-то вроде findAllWithLimitOffset(int limit, int offset)? И таких кейсов достаточно много.
                                                                                                                  Вот кстати ещё один из самых смешных кейсов. Спринг Controller не умеет возвращать файлы! Что бы вернуть файл с контроллера надо заинжектить HttpServletResponse и пробрасывать через оутпут-стрим и хидеры прокидывать. Неужели спринг со своей гибкостью не мог сделать поддержку контроллера с возвращаемым значением File? Или какой-то более компактный и лаконичный способ?
                                                                                                                    +2
                                                                                                                    Спринг Controller не умеет возвращать файлы!

                                                                                                                    Можно без HttpServletResponse:


                                                                                                                       @GetMapping("/...")
                                                                                                                        public ResponseEntity<?> get(...) {
                                                                                                                            final InputStream stream = ...;
                                                                                                                            return ResponseEntity.ok()
                                                                                                                                    .contentType(MediaType.IMAGE_JPEG)
                                                                                                                                    .cacheControl(CacheControl.maxAge(365, TimeUnit.DAYS))
                                                                                                                                    .lastModified(storage.getDate().getTime())
                                                                                                                                    .eTag('\"' + String.valueOf(storage.getId() + storage.getDate().getTime()) + '\"')
                                                                                                                                    .contentLength(storage.getSize())
                                                                                                                                    .body(new InputStreamResource(stream));
                                                                                                                        }
                                                                                                                      +1
                                                                                                                      Вы хотите сказать это краткий и лаконичный код?))))
                                                                                                                      Вот вам пример из Play-a

                                                                                                                      public Response getFile(String path){
                                                                                                                      File file = ....
                                                                                                                      return ok(file)
                                                                                                                      }
                                                                                                                      
                                                                                                                        0
                                                                                                                        Вы хотите сказать это краткий и лаконичный код?))))

                                                                                                                        Вы про хидеры говорили, вот я и дал вам пример с хидерами. Вот короче:


                                                                                                                        @GetMapping("/")
                                                                                                                        public ResponseEntity<?> get() throws FileNotFoundException {
                                                                                                                            File file = ...
                                                                                                                            return ResponseEntity.ok(new InputStreamResource(new FileInputStream(file)));
                                                                                                                        }
                                                                                                                          +1

                                                                                                                          Если хотите большей лаконичности, то создайте класс:


                                                                                                                          public class SendFile extends ResponseEntity<?> {
                                                                                                                              public SendFile(File file) throws FileNotFoundException {
                                                                                                                                  super(new InputStreamResource(new FileInputStream(file)), HttpStatus.OK);
                                                                                                                              }
                                                                                                                          }

                                                                                                                          А потмо везде пишите так:


                                                                                                                          @GetMapping("/")
                                                                                                                          public ResponseEntity<?> get() {
                                                                                                                              File file = ...
                                                                                                                              return new SendFile(file);
                                                                                                                          }
                                                                                                                          
                                                                                                                            +1
                                                                                                                            Ну вот вы и вернулись к тому, о чем писал я.
                                                                                                                            В некотором смысле, спринг обязывает вас говнокодить. Код должен содержать бизнес логику, а не фабрики, интерфейсы, конверторы, дто и т д.

                                                                                                                            Почему, когда я подключаю такой огромный и мощний фрейморк, спринг, я не могу просто написать
                                                                                                                            @GetMapping("/")
                                                                                                                            public File get() {
                                                                                                                                return new File(file);
                                                                                                                            }
                                                                                                                            

                                                                                                                            У спринга есть все возможности для этого, и эту элементарную вещь они могли добавить лет так 7-8 назад. Почему спринг понимает, что POJO можно отдать в Json/XML, String — загрузить шаблон, а файл вызывает просто ужас у спринга? Я не хочу писать кучу конфигов, утилитарных методов, адаптеров и прочей чепухи, используя такой огромный фреймворк. Игры для андроида занимают 50 мегабайт, там куча 3д объектов, миллионы формул и вычислений, а я своём веб-аппе тяну спринг фреймворк весом в 50 мегабайт, который из коробки не понимает что если контроллер возвращает файл — то надо вернуть файл! И это я навел только 2 маленьких и безобидных примера.
                                                                                                                              +1
                                                                                                                              Ну вот вы и вернулись к тому, о чем писал я.

                                                                                                                              Мы пришли к тому, что вы не очень хорошо знаете spring.


                                                                                                                              @GetMapping("/...")
                                                                                                                              @ResponseBody
                                                                                                                              public FileSystemResource get() {
                                                                                                                                  return new FileSystemResource("/path/to/file");
                                                                                                                              }

                                                                                                                              Но не стоит отдавать статические файлы через контроллер. Для файлов есть директория resource и spring.resources.static-locations.

                                                                                                                                0
                                                                                                                                Ой, а может тогда мне совет дадите. Надо сделать сокет сервер на wildfly, а там через JCA и пр. Есть способ попроще что бы восемь классов оберток не делать? Я конечно обошелся сделав сокет клиент, но все же хочется.
                                                                                                                                  +1
                                                                                                                                  Смотрите, за время нашей переписки, здесь было уже упомянуто 3 способа. И не стоит рассуждать о моих знаниях спринга исходя из переписки. 3 способа, какой из них лучше? И речь вообще не идет о том, статик файлы это или нет, вполне возможно что они генерируются на лету и отдаются только авторизированному юзеру и доступны в течении некоторого небольшого времени. А теперь представьте что у вас таких мест много. И у каждого, свой вариант. Как вы потом будете сапортить такой код? И опять таки, это самые безобидные примеры. Ну, повповторюсь, я не призываю кого либо отказываться от спринга и не говорю что он говно. Но некоторые вещи в нем плохие. И есть лучшая альтернатива.
                                                                                                                                    0
                                                                                                                                    3 способа, какой из них лучше?

                                                                                                                                    Решить что лучше — задача архитектора.


                                                                                                                                    ResponseEntity<> позволяет управлять статусом ответа (200 OK, 404 Not Found...). Имеет смысл проверять заголовки запроса и отдавать "304 Not Modified"…
                                                                                                                                    Также позволяет установить Content-Disposition, cacheControl, eTag и прочее.


                                                                                                                                    Если вам это не нужно, то возвращайте из контроллера FileSystemResource или InputStreamResource + @ResponseBody


                                                                                                                                    Если вы захотите автоматизировать установку хидеров и выдачу статуса "304 Not Modified", то можете доработать мой пример с SendFile.

                                                                                                                                  0
                                                                                                                                  Почему, когда я подключаю такой огромный и мощний фрейморк, спринг, я не могу просто написать

                                                                                                                                  У спирнга нет никаких проблем с отдачей файла, zirix написал выше как сделать это одной строкой, если надо. Ваше негодование по поводу того, что спринг-вебмвц гибкий и позволяет сложно кастомизировать ответ прямо из котроллера звучит просто смешно, видимо вам просто никогда не приходилось этим пользоваться.
                                                                                                                                  У спринга есть все возможности для этого, и эту элементарную вещь они могли добавить лет так 7-8 назад.

                                                                                                                                  Примерно 7-8 лет назад это и там и появилось.
                                                                                                                                  Я не хочу писать кучу конфигов, утилитарных методов, адаптеров и прочей чепухи, используя такой огромный фреймворк.

                                                                                                                                  Кто же вас заставляет? Даже если вас насильно засадили писать приложение на спринг-вебмвц, то для простых случаев не нужно писать кучу конфигов, утилитарных методов и прочей чепухи, а вот если нужно что-то кастомизировать, то другой фреймворк может просто в лужу сесть, а в спринге обычно всегда есть способ кастомизировать поведение, как раз во многом из за хорошей модульности и продуманности этого фреймворка и webmvc в том числе.
                                                                                                                                  а я своём веб-аппе тяну спринг фреймворк весом в 50 мегабайт

                                                                                                                                  в теории это возможно если тянуть как минимум 5 разных версий всех зависимостей, но что-то мне подсказывает, что это не будет работать. Я это к тому, что ваша оценка размера спринга более чем преувеличена. Да и не так уже это страшно для нынешних реалий 10 мегабайт, если они удовлетворяют большинству потребностей.
                                                                                                                                  который из коробки не понимает что если контроллер возвращает файл — то надо вернуть файл!

                                                                                                                                  Вы уже трижды продекламировали эту мысль при том, что спринг отлично с этой задачей справляется. У спринга своя абстракция ресурсов и именно её он и поддерживает в качестве возвращаемого значения, что на порядок гибче, чем просто файл. Тем более, что файл это один из видов доступных ресурсов.
                                                                                                                                    0
                                                                                                                                    Я не хочу больше с вами холиварить. В этом нету никакого смысла. Пройдет время, и вы наберетесь опыта, и поймете о чем пишет и автор, и я, и много других людей. Как видите, я не одинок в своем взгляде на спринг.
                                                                                                                                      0
                                                                                                                                      Это не холивар, а указание на неточности вашего комментария, я (честно говоря) и не ждал на него ответа.
                                                                                                                          +1

                                                                                                                          В JPA нет LIMIT. Реализации его — вендор-специфичны. Зато есть Pageable, который вполне можно передать, он и сделан для лимит-оффсета.

                                                                                                                            0
                                                                                                                            Спасибо, я это и так знаю. И говорю о том, что спринг мог бы это делать сам. Ровно так же как он строит и другие запросы по имени метода в интерфейсе репорепозитория.
                                                                                                                              0

                                                                                                                              Они это сделали с помощью другой абстракции — Pageable. Чем она вас не устраивает?

                                                                                                                            0

                                                                                                                            Возвращайте InputStreamResource или FileResourse — это законные действия.

                                                                                                                              0
                                                                                                                              Тоже самое что и в предыдущем коменте. Спринг давно мог бы это делать сам, в зависимости от типа возврвщаемого значения в контроллере.
                                                                                                                                0
                                                                                                                                Зачем? И если вам так этого не хватает — почему не сделаете PR с этой функциональностью? И где можно посмотреть хотя бы на feature request на эту функциональность? Или вы думаете что ребята из pivotal читают мысли разраобтчиков через libastral?
                                                                                                                                Я обычно иду по одному из двух путей — либо делаю PR, либо feature request. Вероятно кто-то выбирает третий путь — пожаловаться на хабре — и ему это помогает, но я не особенно в это верю.
                                                                                                                                  +1
                                                                                                                                  Я не создаю, потому что меня более чем устраивают другие библиотеки и фреймворки. Возможно, если будет время, я напишу пару хороших уроков, как можно писать веб приложения без спринга, и попытаюсь показать все плюсы и минусы.
                                                                                                                                    0
                                                                                                                                    Будет очень круто
                                                                                                                                      +1
                                                                                                                                      Мне кажется неконструктивным ругать то, чем не пользуешься.
                                                                                                                                        0
                                                                                                                                        *пользовался
                                                                                                                            +1
                                                                                                                            Попробуйте пописать годик-два проект например на Play Framework-е, желательно на старом, что бы без DI.

                                                                                                                            Почему без DI? Если DI настолько плох, почему его внедриои в Play?
                                                                                                                            +1
                                                                                                                            Неужели нельзя просто взять и сделать руками (велосипед, если хотите)?
                                                                                                                            Я не первый день занимаюсь разработкой веб-приложений и до сих пор не осилил спринг. Сейчас объясню что имею виду.
                                                                                                                            Когда я прочел книгу про Java EE и про Spring, я прям загорелся: «а что так можно было?». После того как начал искать в сети и пробовать — я почти во всем разочаровался.

                                                                                                                            1. Тот же DI — крутая штука, но я так и не понял когда ее крутость может пригодиться в бою. Мне всегда было достаточно Singleton-ов и ThreadLocal-переменных. Аналоги Session-бинов, по-моему уже не нужны, больше проблем будет, чем пользы; это можно сказать в целом про сессии на сервере.

                                                                                                                            2. @RequestMapping("/helloWorld"). По сути мы выставляем метод наружу. И этот маппинг — дополнительная, на мой взгляд, не нужная абстракция. В своих приложениях я выставил методы наружу по их собственному имени, например, /ru/example/Booking.list?param1=… Это понятнее.
                                                                                                                            Превратить get-параметры в параметры вызова, а результат функции в json не составило труда. Это действительно очень просто сделать.

                                                                                                                            3. Security. Все очень здорово придумано: определяешь роли и ассоциируешь их с пользователями. А методы с ролями. Но в бою это работает плохо и неэффективно, потому что в большой организации обязанности перекладываются из роли в роли постоянно. То одним нужен отчет, то другим. Кому-то можно заселять задним числом, кому-то нет (я про отель). Таких примеров каждый день прибавляется — грани между ролями плавающие. К тому же часто права должны быть параметрическими (например, хочется задать за какое количество дней назад человек может сделать отчет или, допустим, инспектор в отеле имеет доступ в раздел номера, но вносить правки должен мочь только для своего корпуса).
                                                                                                                            Каждый раз пересобирать и перевыкладывать проект из-за этого не хочется.
                                                                                                                            В своем проекте я иначе это реализовал.
                                                                                                                            Есть security-классы, которые описывают те или иные права. Для каждой роли (которые хранятся в базе) задается список классов и их значения (в виде json-а, например)

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

                                                                                                                            Это более гибко и типобезопасно.

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

                                                                                                                            Удивительно, но все это реализовано классами, которые можно пересчитать пальцами рук (ну, возможно и ног). Это действительно очень просто и новый программист быстро поймет как и что работает. И никакой магии. Проект деполится в Tomcat-е меньше чем за секунду. И при этом я не перетрудился, я же программист.

                                                                                                                            Ну и не стоит забывать про KISS:
                                                                                                                            На мой взгляд у почти всех back-end приложений две основных задачи:
                                                                                                                            1. положить в базу то что прислал пользователь,
                                                                                                                            2. взять что-то из базы и отправить пользователю.
                                                                                                                            Не усложняйте.
                                                                                                                              –4
                                                                                                                              тормознутая сама по себе жаба, жрущая гигабайты оперативки плюс тормознутый xml где данные хранятся нерациональным способом в виде текста вместо бинарного способа(что создает избыточность представления, необходимость парсинга, сложность поиска)
                                                                                                                                +4
                                                                                                                                Тружусь в относительно большом проекте, несколько сотен тысяч строк кода, все на Spring'е, пока все хорошо.
                                                                                                                                Хочется сказать пару слов в защиту:
                                                                                                                                • Магия — это действительно плохо. Ряд приемов, например, autoscan, лучше использовать с осторожностью или не использовать совсем, тем более что магия часто замедляет инициализацию контекста.
                                                                                                                                • Конфигурировать лучше с помощью Java конфига. Будет вам compile time safety.
                                                                                                                                • Импортировать Java конфиги не легко, а очень легко.
                                                                                                                                • Spring умеет очень много, сложность его велика, но документация очень неплоха, а главное — никто не вываливает всю эту сложность на программиста за раз. Обычно бывает наоборот: нужна какая-то штука, и в попытках найти решение вдруг оказывается, что в Spring'е есть и это!
                                                                                                                                • Подъем контекста Spring'а крупного приложения занимает заметное на глаз время, поэтому в тестах лучше Spring'ом не злоупотреблять. Если же оказывается, что без Spring'а протестировать класс, например, нереально — вы что-то делаете не так.
                                                                                                                                • Spring сам по себе не делает мир лучше. Если бардак в головекоде — начинать надо не со Spring'а.


                                                                                                                                  0
                                                                                                                                  Конфигурировать лучше с помощью Java конфига. Будет вам compile time safety.


                                                                                                                                  Компилятор таки сможет проверить, что всё заавтовайрится?

                                                                                                                                  а главное — никто не вываливает всю эту сложность на программиста за раз


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

                                                                                                                                  Если же оказывается, что без Spring'а протестировать класс, например, нереально — вы что-то делаете не так.


                                                                                                                                  А именно — используем Spring в проекте. Шутка (но с долей правды).

                                                                                                                                  Если бардак в головекоде — начинать надо не со Spring'а.


                                                                                                                                  Вообще это здравая мысль, вот только почему-то в поддержку Spring часто звучит такой «аргумент», что он якобы учит молодежь правильной архитектуре.
                                                                                                                                    +1
                                                                                                                                    А именно — используем Spring в проекте. Шутка (но с долей правды).

                                                                                                                                    Класс принимает зависимости в конструкторе, в тесте просто создаете новый инстанс класса и передаете зависимости, Spring тут не обязателен.
                                                                                                                                      +2
                                                                                                                                      Компилятор таки сможет проверить, что всё заавтовайрится?

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

                                                                                                                                      В этом высказывании можно заменить Spring на любую другую не самую простую технологию, смысл особо не изменится. Но, честное слово, я не видел такого не разу. Либо джун Василий не совсем пустоголовый и способен обучаться, либо он не пройдет собеседование и не попадет в проект.
                                                                                                                                      А именно — используем Spring в проекте. Шутка (но с долей правды).

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

                                                                                                                                      Виноват ли в том Spring?
                                                                                                                                        +1
                                                                                                                                        Нет, конечно, но при использовании java он позволяет гарантировать, что при наличии всех зависимостей компонент инициализируется корректно.


                                                                                                                                        Звучит как «если вы всё сделали правильно и ничего не забыли, компонент гарантированно инициализируется корректно». Вот у меня Spring-конфигурация на Java и, по моему опыту, она вообще ничего не гарантирует. Проект скомпилируется и обосрется через 2 минуты инициализации контейнера, потому что тут не завайрился бин, а тут пропертю забыли подсунуть в файл. Вот это удовольствие автор и имел в виду, когда говорил, что в Spring нет compile time safety.

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


                                                                                                                                        Ну т.е. на него таки вываливают всё это дерьмо сразу.

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


                                                                                                                                        Виноват ли в том Spring?


                                                                                                                                        Еще как виноват, потому что хеллоуворлды на нем выглядят просто и весело, создавая иллюзию, что вот за тебя крутые дядьки подумали и сделали мегафреймворк на все случаи жизни, а ты просто пишешь 2 строчки кода — и вуаля, у тебя сама собой вырастет шикарная архитектура и все девки будут твои.
                                                                                                                                          0
                                                                                                                                          Звучит как «если вы всё сделали правильно и ничего не забыли, компонент гарантированно инициализируется корректно». Вот у меня Spring-конфигурация на Java и, по моему опыту, она вообще ничего не гарантирует. Проект скомпилируется и обосрется через 2 минуты инициализации контейнера, потому что тут не завайрился бин, а тут пропертю забыли подсунуть в файл. Вот это удовольствие автор и имел в виду, когда говорил, что в Spring нет compile time safety.

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

                                                                                                                                          В зрелом проекте дерьмо неизбежно. Если не Spring, то еще что-нибудь.
                                                                                                                                          Еще как виноват, потому что хеллоуворлды на нем выглядят просто и весело, создавая иллюзию, что вот за тебя крутые дядьки подумали и сделали мегафреймворк на все случаи жизни, а ты просто пишешь 2 строчки кода — и вуаля, у тебя сама собой вырастет шикарная архитектура и все девки будут твои.

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

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

                                                                                                                                            Звучит как «если вы взяли какую-то другую библиотеку, то она не падает в рантайме если ей забыли пропертю подсунуть в файл».
                                                                                                                                            Ну т.е. на него таки вываливают всё это дерьмо сразу.

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

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

                                                                                                                                            Еще хочу заметить, что спринг в первую очередь это система интеграции сторонних библиотек и решений, а не какие-то конкретные решения (хотя конечно и они есть), более того обычно ты можешь выбирать какие реализации ты будешь использовать и из коробки идет несколько. Я это к тому, что спринг не просто не исключает использования набора простых решений, но напротив именно к тому тебя и подталкивает и предоставляет удобные способы их интегрировать в приложение, многие прямо из коробки.
                                                                                                                                              +1
                                                                                                                                              Да, есть di контейнеры, которые гарантируют консистентность на уровне компиляции, но это накладывает другие серьезные ограничения на них, которых у спринга нет. Выбирайте, что вам важнее.


                                                                                                                                              А бывает DI вообще без контейнеров, который еще и валидируется компилятором.

                                                                                                                                              Нет, обычно проблемы появляются по одной


                                                                                                                                              Ты можешь позволить себе такую роскошь, когда начинаешь проект в одиночку. А когда ты вливаешься в уже довольно большой проект… Из моего личного опыта: приходишь на проект, а там — куча магии: Spring, Hibernate, Spring Data JPA, Dozer, AspectJ и прочий reflection. У меня ушло примерно полгода на то, чтобы во всем этом более-менее разобраться и начать делать более-менее серьезные изменения. И не надо мне рассказывать, что это я такой дурак. Я себе цену знаю.

                                                                                                                                              То есть вы искреннее считаете, что тот факт, что вы не можете сделать большое приложение на спринге, означает, что никто не может?


                                                                                                                                              То есть вы искренне считаете, что спринг могут ругать только неосиляторы? Ну если считать Spring верхом совершенства, то конечно. А если ненадолго включить логику и воображение, можно подумать о людях, которые просто осилили и переросли Spring. Кто-то расширял кругозор и нашел что-то более удобное (даже если только для его проекта). Кто-то заглянул под капот Spring и не увидел там ничего сверхъестественного, а просто набор паттернов, одни из которых реализованы удачно, другие — не очень, третьи — вообще отвратительно. Ну а для кого-то Spring так и остался шайтан-машиной с книгой @Заклинаний.
                                                                                                                                                0
                                                                                                                                                Из моего личного опыта: приходишь на проект, а там — куча магии: Spring, Hibernate, Spring Data JPA

                                                                                                                                                У Вас на тот момент был уже опыт работы со Spring и Hibernate?
                                                                                                                                                  0
                                                                                                                                                  У Вас на тот момент был уже опыт работы со Spring и Hibernate?


                                                                                                                                                  Был — в этом вся соль.
                                                                                                                                                    0

                                                                                                                                                    И что же там было трудно понять? Обычно приложение на Spring это куча сервисов с DI, Spring Security и Spring Jdbc

                                                                                                                                                      +1
                                                                                                                                                      Когда в приложении полно рефлексии, неочевидных использований имен из кода (например, Spring Data JPA), не отслеживаемых нормально без IDE, это парево вообще всегда, тем более поначалу. Потому что у меня одна из самый частых задач — найти все места, где используется такая-то сущность (колонка, поле и т.д.). А если в проекте полно магии, приходится постоянно помнить, где и как она используется, потому что стандартные поиски и рефакторинги IDE по коду не помогают, и действия, которые должны быть простыми, превращаются в квест. Это не нормально — это моя принципиальная позиция, и если кто-то не согласен, то дальше нам просто нечего обсуждать.
                                                                                                                                                        +2
                                                                                                                                                        Т.е. у вас были проблемы не с Spring а с Spring Data JPA :)
                                                                                                                                                        Вместо него можно взять Spring JDBC без рефлексии
                                                                                                                                                          0

                                                                                                                                                          строго говоря и Spring Data JPA можно без рефлекции готовить

                                                                                                                                                            0
                                                                                                                                                            Можно много без чего, и без спринга тоже.
                                                                                                                                                            Spring Data JPA — это всего лишь частный пример, не надо к нему цепляться. Отрубите голову гидре — а там еще куча этих голов.
                                                                                                                                                    +1
                                                                                                                                                    А бывает DI вообще без контейнеров, который еще и валидируется компилятором.

                                                                                                                                                    Я так и написал.
                                                                                                                                                    У меня ушло примерно полгода

                                                                                                                                                    Тут конечно у каждого будут разные сроки на освоение, но главное, что один раз потратив это время, в любом другом проекте вам не нужно тратить пол года, чтобы разобраться с местными велосипедами, а вы просто начинаете писать код. Да это не золотая пуля, он далек от идеала. Но его делает толковая команда с хорошим qa, его знают разработчики, он решает реальные задачи и развивается. Этого достаточно, чтобы выбрать его вместо самописного решения.
                                                                                                                                                    То есть вы искренне считаете, что спринг могут ругать только неосиляторы?

                                                                                                                                                    Ругайте на здоровье. Я нисколько не против. Просто вы написали, что на спринге только хеловорлды хорошо идут, что я честно говоря могу объяснить только тем, что вы просто не умеете его готовить. Что в целом тоже не зазорно, потому что я бы не назвал его простым и как тут выше замечали он требует поиска своего пути, в том плане, что на нем можно решать проблемы очень по-разному, что приводит к разной архитектуре и разному пониманию происходящего. Так что я нисколько не против того, что кому-то из за этого или по другом причинам этот фреймворк не нравится. Как я уже писал выше, выбирайте фреймворк по себе и по потребностям, кому как удобнее это по большому счету вкусовщина.
                                                                                                                                                      +1
                                                                                                                                                      один раз потратив это время, в любом другом проекте вам не нужно тратить пол года, чтобы разобраться с местными велосипедами


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

                                                                                                                                                      А если «велосипед» грамотно написан, там не в чем разбираться, т.к. всё делается очевидно, прозрачно и локально, и когда нужно что-то исправить, ты спокойно делаешь это в одном месте, а не шерстишь весь проект в поисках подвоха.
                                                                                                                                                        0
                                                                                                                                                        А если «велосипед» грамотно написан, там не в чем разбираться, т.к. всё делается очевидно

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

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

                                                                                                                                                          0
                                                                                                                                                          Обычно под словом «магия» я подразумеваю, что всё сделано через жоreflection.

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


                                                                                                                                                          Шаг влево, шаг вправо…
                                                                                                                                                            0

                                                                                                                                                            тесты тоже через жоreflection работают

                                                                                                                                                              0

                                                                                                                                                              Тесты не сильно смущают обычно. Они таки в проде не запущены.


                                                                                                                                                              Конечно, когда it-suite выполняется час-другой, то очень хочется оптимизации, но это другая проблема.

                                                                                                                                                                0
                                                                                                                                                                Тот факт, что я готов смириться с рефлексией в тестах, не означает, что я хочу плодить ее везде, особенно в основном коде.
                                                                                                                                                                –2
                                                                                                                                                                Так и всё же, что же там за страшная рефлексия такая, не эта случаем?
                                                                                                                                                                  0
                                                                                                                                                                  Reflection
                                                                                                                                                      0
                                                                                                                                                      а тут пропертю забыли подсунуть в файл. Вот это удовольствие автор и имел в виду, когда говорил, что в Spring нет compile time safety.

                                                                                                                                                      Ну да, ну да. Пропертю в файл забыли — а виноват спринг? Если вы позволяете кому-то настраивать приложение, изменяя что-то в файле (который очевидно не компилируется), то что вы от фреймворка хотите? Да, этот кто-то может ввести строку вместо числа. И что?


                                                                                                                                                      Сорри, может вы не то имели в виду — но именно так оно почему-то и выглядит. Нет compile time safety во многих случаях — когда у вас в проекте база, она вам этого не гарантирует, когда у вас вообще любые внешние данные. И никто кроме вас этого гарантировать не может.

                                                                                                                                                        0
                                                                                                                                                        Проблема с пропертей в том, что я узнаю о ней через несколько минут после запуска приложения.
                                                                                                                                                          0
                                                                                                                                                          Вы интеграционные тесты пишите? Если с пропертями что-то будет не так вы поймаете это в тестах
                                                                                                                                                            +1
                                                                                                                                                            А разве интеграционные тесты не требуют поднятия всей системы?
                                                                                                                                                              0

                                                                                                                                                              Ну да, тогда Вы и узнаете что есть проблемы

                                                                                                                                                                0
                                                                                                                                                                Так, это уже другая тема. Речь была о том, что Spring стартует долго. Проперти — дело десятое.
                                                                                                                                                                  0
                                                                                                                                                                  И Вы хотите чтобы эти проперти проверялись на этапе компиляции?