tgoop.com/Java_Iibrary/1846
Last Update:
Сценарный вопрос с реального интервью по Java/Spring Boot:
В контроллере вызывается метод сервиса, помеченный аннотацией @Transactional
.
Этот метод не только сохраняет сущность, но и отправляет два письма: одно администратору, другое — пользователю, который сделал запрос.
Класс, отвечающий за отправку почты, помечен аннотацией @Async
, но Spring всё равно выполняет его синхронно.
В итоге API обрабатывает запрос целых 12 секунд — очевидно, это неприемлемо.
Вопрос: почему так происходит и как это исправить?
Реальная причина:
Когда используется @Transactional
, Spring создаёт прокси для транзакции.
Если внутри этого же контекста вызывается @Async
-метод, то Spring не создаёт новый поток — потому что вызов происходит внутри того же прокси.
Иными словами, асинхронный код оказывается «заперт» внутри транзакции.
В результате, коммит в базу ждёт, пока оба письма не будут отправлены.
Как исправить:
Заменить прямой вызов отправки писем на event-publisher подход.
После сохранения запроса просто опубликовать событие, например DemoRequestCreatedEvent.
Асинхронные слушатели (@EventListener
+ @Async
) будут обрабатывать отправку писем вне основной транзакции.
Что получаем:
Транзакция завершается за ~100 мс вместо 12 секунд.
API реагирует почти мгновенно.
Письма всё так же надёжно уходят в фоне.
Использование событий и асинхронных слушателей — не просто красивая архитектурная штука, а реальный способ сделать систему быстрой, масштабируемой и профессиональной.
Дополнительный вопрос:
Кроме событий, какие подходы ты используешь, чтобы отделить транзакционную логику (например, коммит в БД) от побочных эффектов вроде отправки писем или уведомлений?
@Java_Iibrary
BY Java Portal | Программирование
Share with your friend now:
tgoop.com/Java_Iibrary/1846