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



Почему @Transactional иногда НЕ работает?
Представим обычный сервис:

@Service
public class OrderService {

@Transactional
public void createOrder() {
saveOrder();
}

@Transactional(propagation = REQUIRES_NEW)
public void saveOrder() {
// отдельная транзакция
}
}

Кажется, что saveOrder() запустится в новой транзакции.
Но нет. 😈Если вызвать:
createOrder();
то saveOrder() вызывается напрямую через this.
А Spring работает немного иначе.
Когда контейнер создаёт Bean, вокруг него может появиться Proxy:
OrderService
↑
│
Spring Proxy
│
└── @Transactional
Вызов извне:
orderService.createOrder();
проходит через Proxy:
Controller
↓
Proxy
↓
Transaction
↓
OrderService
А вот внутри самого объекта:
this.saveOrder();
Proxy уже не участвует:
OrderService
↓
this.saveOrder()
Поэтому Spring не видит этот вызов и не может применить к нему REQUIRES_NEW.
И вот здесь часто возникает вопрос на собеседовании:

Почему @Transactional стоит на методе, но транзакция не создаётся

?Ответ:
Аннотация сама по себе ничего не перехватывает.

Spring использует AOP и Proxy, а значит вызов должен пройти через Proxy.
Поэтому такой код:
this.saveOrder();
может вести себя совсем не так, как ожидает разработчик.
Главная мысль:

Когда видите @Transactional, думайте не только про транзакцию.
Думайте:
Bean → Proxy → AOP → вызов метода.

И тогда половина «магии Spring» становится обычной механикой. 😉
Просмотры: 39
Открыть в MAX Сообщить о неточности

Репосты публикации

Публикация канала

Сообщить о неточности

Опишите, что нужно исправить. Если есть источник, добавьте ссылку.

Вы покидаете datool.ru

Ссылка ведёт на внешний сайт. datool.ru не отвечает за его содержимое — проверьте адрес, прежде чем вводить пароли или платёжные данные.

Переход через 10 с

Перейти