Одна из старых и вполне понятных особенностей Spring в том, что singleton бины во время
ApplicationContext refresh создаются синхронно. Контейнер идет по цепочке последовательно: создал бин, внедрил зависимости, выполнил init-логику, пометил как готовый, пошел дальше.Модель надежная, но дорогая по времени. Если в этой цепочке оказывается бин, который на старте прогревает кеш, тянет данные, готовит внешние ресурсы или делает что-то вычислительно тяжелое, он начинает тормозить не только себя, а весь startup целиком. Даже если этот бин не критичен для первых секунд жизни приложения, контекст все равно вынужден его ждать.
💡 Теперь для таких сценариев, начиная со Spring 6.2 есть background initialization.
Можно указать
@Bean(bootstrap = Bean.Bootstrap.BACKGROUND), благодаря которой можно пометить конкретный бин так, чтобы Spring инициализировал его в фоне, а основной поток не стоял на месте и продолжал поднимать остальной контекст. Тяжелый бин больше не тормозит весь context refresh.⚠️ Для инициализации в бекграунде нужен
bootstrapExecutor (по-умолчанию, Spring Boot принесёт его самостоятельно).Но тут очень важно понимать, как это работает. Комментарий от Михаила:
Работает эта история таким образом - в injection point-ах, где нужен bean, кладётся proxy. Тем самым удовлетворяется зависимость. И вот тут крайне важно - если на этом proxy будет вызов метода, то он будет заблокирован до тех пор, пока реальный ваш bean не инициализируется. В данном случае это похоже на динамику работы Lazy, но не на declaration site-е, а на injection point-е.
И ещё вот что важно: даже если вы отдали инициализацию бина в background, Spring Boot не завершит фазу refresh-а до тех пор, пока не встанет этот ваш бин. Это важно, чтобы потенциально сломанное приложение не начало serve-ить трафик.
Есть очень хороший доклад от Juergen Hoeller-а, который он давал в Барселоне в 2025г, посмотрите его. У вас прямо много вещей встанет в голове в нужные места.
Если подытожить, Spring теперь позволяет не блокировать весь startup на тяжелых, но не критичных бинах, при этом не ломая lifecycle и dependency guarantees.