Создастся ли транзакция, если метод без @Transactional вызывает метод с @Transactional внутри одного Spring-бина?

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

Ответ

Нет, транзакция не создастся из-за ограничения механизма AOP в Spring.

Причина: Управление транзакциями реализовано через прокси-объекты. Вызов метода внутри того же класса (this.innerMethod()) обходит прокси, и аннотация @Transactional игнорируется.

Проблемный сценарий (самовызов):

@Service
public class MyService {
    // Вызывается клиентом -> работает через прокси
    public void outer() {
        inner(); // Самовызов! Прокси не участвует -> НЕТ ТРАНЗАКЦИИ
    }

    @Transactional // Аннотация не сработает
    public void inner() {
        // Операции с БД не будут защищены транзакцией
    }
}

Решение:

  1. Инъекция самого себя (через @Autowired):

    @Service
    public class MyService {
        @Autowired
        private MyService self; // Ссылка на прокси
    
        public void outer() {
            self.inner(); // Вызов через прокси -> транзакция создается
        }
        @Transactional
        public void inner() { ... }
    }
  2. Вынос в отдельный бин.
  3. Использование TransactionTemplate для программного управления.

Важно: Если вызов идет между разными бинами, транзакция создается корректно, так как вызов проходит через прокси.