Что нельзя сделать в конструкторе Spring Bean
Что проверяют
Понимаете ли вы жизненный цикл бина и то, что до выхода из конструктора перед вами ещё не бин, а обычный объект: прокси нет, поля не проставлены, контекст не готов.
Как отвечать
Сразу снимите частое заблуждение: внедрять зависимости через конструктор можно и нужно, это рекомендуемый способ. Ограничения совсем другие.
- Нельзя рассчитывать на то, что приходит через поля и сеттеры:
@Autowiredна поле и@Valueна поле проставляются после конструктора, внутри там пусто. - Нельзя пользоваться тем, что работает через прокси.
@Transactional,@Async,@Cacheableи@Scheduledоборачивают уже готовый объект, поэтому вызов такого метода из конструктора идёт мимо обёртки: транзакции не будет, асинхронности тоже. - Нельзя считать внедрённые зависимости полностью готовыми: их собственная инициализация могла ещё не отработать. А циклическую ссылку через конструкторы контейнер вообще не разрешает, приложение падает на старте.
- Нельзя публиковать
thisнаружу: регистрировать себя в слушателях, планировщиках, отдавать в другой поток. Объект ещё недостроен. - Не стоит ходить в сеть и базу: это удлиняет старт, ломает тесты контекста и превращает падение в непонятную ошибку создания бина.
Что делать вместо: тяжёлую инициализацию выносят в @PostConstruct, SmartInitializingSingleton или обработчик события готовности приложения, а зависимость, нужную позже, берут через ObjectProvider или помечают @Lazy.
Где спотыкаются
Заявляют, что бины в конструктор внедрять запрещено. Наоборот: обязательные зависимости берут именно так, поле становится final, объект невозможно создать наполовину собранным, а класс тестируется без поднятия контейнера.
Второе: считают, что из конструктора нельзя бросать исключения. Можно, и часто нужно: проверка конфигурации с падением на старте лучше, чем неопределённое поведение под нагрузкой. Плохо другое, поймать исключение и оставить полуживой объект.
Третье: забывают про области видимости и про свойства. Бин с областью запроса в конструкторе синглтона напрямую не получить, нужен прокси или провайдер, а значения конфигурации, привязанные через сеттеры, в момент вызова конструктора ещё не проставлены.