В Spring: что произойдет, если публичный метод с @Transactional вызовет приватный метод, аннотированный @Transactional(propagation = REQUIRES_NEW)?

«В Spring: что произойдет, если публичный метод с @Transactional вызовет приватный метод, аннотированный @Transactional(propagation = REQUIRES_NEW)?» — вопрос из категории Spring, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Аннотация @Transactional будет проигнорирована, и приватный метод выполнится в рамках существующей транзакции публичного метода. Новая транзакция не создастся.

Причина: В Spring управление транзакциями реализовано через AOP-прокси. Прокси-объект перехватывает вызовы только публичных методов. Вызов приватного метода происходит напрямую, минуя прокси, поэтому его аннотации не обрабатываются.

Пример проблемного кода:

@Service
public class MyService {
    @Transactional
    public void publicMethod() {
        // Выполняется в транзакции Tx1
        privateMethod(); // Аннотация REQUIRES_NEW игнорируется!
        // Код продолжает выполняться в Tx1
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    private void privateMethod() {
        // Фактически выполняется в той же транзакции Tx1
    }
}

Решение для создания новой транзакции:

  1. Сделать метод public (или protected).
  2. Вызвать его не напрямую через this, а через внедренную ссылку на прокси-объект сервиса.
@Service
public class MyService {
    @Autowired
    private MyService self; // Внедряем прокси-объект

    @Transactional
    public void publicMethod() {
        // Транзакция Tx1
        self.requiresNewMethod(); // Вызов через прокси -> создается Tx2
        // Возврат в Tx1
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void requiresNewMethod() { // Метод должен быть public
        // Выполняется в новой, независимой транзакции Tx2
    }
}