Что произойдет при вызове транзакционного метода из нетранзакционного в Spring?

«Что произойдет при вызове транзакционного метода из нетранзакционного в Spring?» — вопрос из категории Spring, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Транзакция не будет создана из-за особенностей работы Spring AOP (проксирование). Аннотация @Transactional обрабатывается Spring-прокси, который перехватывает только внешние вызовы.

Пример проблемы:

@Service
public class UserService {

    public void nonTransactionalMethod() {
        // Внутренний вызов - транзакция НЕ создается
        transactionalMethod(); 
    }

    @Transactional
    public void transactionalMethod() {
        // Операции с БД выполняются без транзакции
    }
}

Почему так происходит:

  • Spring создает прокси вокруг бина
  • @Transactional перехватывается только при вызове через прокси
  • Внутренние вызовы внутри класса обходят прокси

Решения:

  1. Вынести метод в отдельный сервис
  2. Использовать самовызов через AopContext:
    ((UserService) AopContext.currentProxy()).transactionalMethod();
  3. Применить TransactionTemplate:
    transactionTemplate.execute(status -> {
    // транзакционная логика
    return null;
    });
  4. Использовать аспекты с режимом AspectJ (compile/load-time weaving)