Вопрос проверяет понимание того, как Spring применяет AOP и почему транзакции не всегда работают так, как ожидается.
@Transactional в Spring работает через прокси. При self-invocation метод вызывается внутри того же объекта, минуя прокси. В результате транзакция не создаётся и аннотация игнорируется. Это ограничение прокси-механизма Spring. Для корректной работы нужен вызов через прокси.
Self-invocation — это ситуация, когда метод одного класса вызывает другой метод того же самого класса напрямую.
@Service
class OrderService {
public void outer() {
inner(); // self-invocation
}
@Transactional
public void inner() {
// транзакционный код
}
}
@TransactionalSpring:
создаёт прокси вокруг бина
перехватывает вызовы методов
открывает и закрывает транзакции
Транзакция создаётся только при вызове через прокси.
При вызове inner():
вызов происходит напрямую
прокси не участвует
аспект транзакции не применяется
Распространённые подходы:
вынести транзакционный метод в другой бин
вызывать метод через ApplicationContext
использовать TransactionTemplate
@Transactional работает только при вызове через Spring-прокси. Self-invocation обходит прокси и делает аннотацию неэффективной.