Комментарии 19
Разобраться в жизненном цикле бина в Spring бывает непросто: информация разбросана, а объяснения часто сложные и перегруженные деталями.

Не согласен, очень сложно разбираться, особенно по ру книгам
Тем кто использует Spring boot для нагруженных пром решений стоит несколько раз подумать "а стоит ли".
И эта статья еще один намек на это.
Cлушаешь на HighLoad++ выступления "а что мы делали что бы Spring Boot приложения при старте не выжирали все ресурсы и как нам это не очень помогло"
"не очень помогло" - это вывод не особо озвучен, но из результа в 10-15% после сложных приседаний это явно видно.
Отказался на проме от SpringBoot в принципе. Регулярно приходят из эксплуатации с вопросом "вот как бы при поднятии резервного сервера (сервисов на нем в количетве от 500 штук) сократить потребление ресурсов и уменьшить время старта". Если для приложений, где сам определил какая часть в какой последовательности стартует и что можно оптимизировать, как то можно что то сделать, то SpringBoot пока все не загрузит и не подготовит окружение для запуска прикладного кода - жрет ресурсы как свинья помои.
Кстати, здраствуйте ярые поклонники "не монолитов" где каждая мелкая хрень стартует отдельно в своем OS процессе.
Конечно писать на на SpringBoot проще. Как бы магия бинов и аннотаций (до тех пор, пока не слокнешься с нетривиальной проблемой/требованием от эксплуатации и не потратишь пару дней в копании исходников Spring) .
Но не принципиально сложнее, когда приходится руками организовывать все самому. Пусть даже в 2 раза больше времени потратитшь (в основном на продумываение архитектуры). Но за то потом не придется ночью вставать на инциденты с "не хватало памяти.. процессор 100% занят. Все зависло из за этого при старте"
Удобство программиста обратно пропорционально производительности и потреблению ресурсов сервиса. По моим наблюдениям.
Согласен с каждым словом, но хотелось бы добавить ещё про Hibernate, хоть это отдельная библиотека, но является почти неотъемлемой частью Спринга. И с ней так же нагруженные решения не совместимы.
Да еще SpringBoot на нее сверху свое накладывает на чистый hibernate.
Я одном нагруженном (сейчас) модуле я поленился на голом SQL писать. Взял Hibernate (без Spring).
А теперь и полностью переписывать как то не очень. Модуль отвественный и переделывать/перетестировать все что накопислось это и страшно и больно.
Вопрос даже не во времени на переделку. Риски финансовые велики в случае сбоев/ошибок в ПО.
вот и приходится местами по мере нахождения узких высоконагруженных мест фактически на hibernate "sql" писать, что бы оптимизировать SQL запросы и транзакционность.
Уж лучше бы сразу на голом SQL..
Фраза "это же удобно для прототипирования" - это дорога в ад. Когда неожиданно прототип превращается в высоконагруженный сервис. И жуешь потом этот кактус вечно.
Когда неожиданно прототип превращается в высоконагруженный сервис
Если у вас "неожиданно" сервис стал высоконагруженным, то это не проблема Hibernate. А исключительно ваша проблема выбора неверного инструмента.
фактически на hibernate "sql" писать
Так и пишите не на "фактически hibernate sql", а прям на нативном sql. Надо было брать со спрингом, тогда бы Spring Data позволил это делать довольно удобно. В итоге, у вас рутинные запросы (CRUD) пишутся декларативно, а сложные/тяжелые запросы вы пишете руками на чистом sql. Получается и быстро и без кучи рутиннного кода. Это на случай, когда сервис "неожиданно" стал высоконагруженным. А так советую посмотреть в сторону Spring Data Jdbc
В этом случае можно переключиться на Jooq, а для того, чтобы на старте спринг не съедал все что можно и нельзя, то можно можно использовать GraalVM, и запускаться будет намного быстрее.
Да. Слышал и такой вариант. Только на Axiom JDK особой разницы не заметно на тестах.
А еще можно вынести файлы *.class из jar архива. А еще можно *.class положить в FS созданный в RAM и.. иного еще я слышал путей (на коференциях и в кулуарах) как ускорить старт SpringBoot приложения.Включая даже такую экзотику, как собственный форк SpringBoot для того что бы делать "прогрев". (не помню что подразумевали авторы. давно было)
А можно просто не использовать SpringBoot для высоконагруженных сервисов Java которым требуется быстрый старт.
Есть опыт переписывания HTTP сервисов со Spring на "просто страрт из main http сервера с REST API+пул jdbc коннектов".
не так уж много дополнительно кода требуется, что бы явно указывать зависмости, пользоваться @Ingect "из коробки" и самому обрабатывать анотации там где это нужно, а не по всем классам прикладного кода. Ничего сложного в этом нет.
после такой переделки, ресурсы, потребляемые сервисом для старта сокращаются кардинально.
Есть с чем сравнивать. И это важно для прома, когда из железа нужно выжать максимум.
Почему то все просто помешались на этом SpringBoot. Как будто ничего другого нет.
SpringBoot, в сущьности, довольно простой, если брать основу (автоматические связи между компонентами прикладного кода). А все остальное в нем, это зачастую кривонаписанные обертки поверх других продуктов/либ (Hibernate, Http сервера, kafka и пр.).
А насчет Jooq... Когда тратишь кучу времни, что бы найти как добавить в SQL, который порождает Hibernate, специфичный вариант синтаксиса (а hibernate типа как бы "сам лучше знает чем я"), то собрать грабли на другой дорожке уже не хочется.
Можете показать пример, как вы описываете контроллеры без спринга и других фреймворков?
Отказаться от Boot - это ещё не значит отказаться вообще от Spring. Да и есть фреймворки, кроме спринга, которые работают не на рефлексивной магии.
Spring обертывет своим кодом и kafka и Tomcat под свои особенности.
Но вообще никто не мешает использовать kafka даже внутри Springboot напрямую.
Особенно, когда хочется использовать какую ни будь фичу либы клиента kafka, а разработчики SpringBoot не захотели (посчитали не нужным) вынести ее в API Spring.
..
final KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
..
while (!Thread.interrupted()) {
..
ConsumerRecords<String, String> records = consumer.poll(Duration.ofSeconds(dt));
То же самое и с реализацией API web, которая есть у всех Http серверов (tomcat, grizzly, jetty,..)
Дело вкуса, но стандарт анотаций javax.ws.rs.* @POSTT, @Path, @Consumes,..) мне больше нравится чем "стандарт" анотаций Spring @RequestMappingg). Хотя это субъективно и не имеет никакого принципиального значения.
Кстати, во всех Http серверах "из коробки" есть поддержка @Inject в реализации классов API. Конечно, не автоматом сборка бинов, а нужно руками при старте сервера указать какие классы хочешт инжекнуть и как.
В общем, список того что мне не нравится в SpringBoot (в порядке приоритета)
Автоматический сбор зависимостей это удобство для программиста, но большая нагрузка и ресурсы сервера на старте программы.
Оболочки Spring вокруг стандартных либ подходят для 99% задач, но когда возникает что то не стандартное, то либо нужно пробиваться к нужным вызовам через рефлексию, по пути долго матерясь и копаясь в исходниках Spring или использовать вызовы либ напрямую. В общем, шаг в строну - уже проблема.
Красота и удобство кода не = производительности. Местами приходилось красивый "функциональный" вызов stream заменять на не красиывый for ради экономии долей ms.
Да. Сейчас набежит куча советчиков типа "советую посмотреть в сторону Spring Data Jdbc". Даже отвечать им не буду. Осорбенно когда потратил дни копаясь в исходниках Spring.
Прекрасно знаю как Spring работает, как использует пулы JDBC, накручивая вокруг них свой код.
Тут то при работе с пулами jdbc коннектов напрямую возникают тонкие, сложно уловимые (на проме) проблемы. А когда вокруг еще код Spring - это вообще не реально разобраться в причинах.
Так что не надо советовать.
Мне все равно на чем писать. И на том и на сем много писал.
дубликат
статья негодная, никаких примеров кода. Зачем мне эти кофеварки и прочее
Spring создает объект бина с помощью конструктора, но пока не внедряет в него зависимости.
Как бы противоречит
Способы внедрения зависимостей:
Через конструктор...
На сегодня практически самый распространенный способ внедрения зависимостей через конструктор. Кмк.
Жизненный цикл бина в Spring