Я поговорю о Spring и @Transactional, но рекомендации применимы и ко многим другим фреймворкам.
Это неотъемлемая проблема с аспектами, основанными на прокси.Это обсуждается в весенней документации здесь:
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-understanding-aop-proxies
Существует множество возможных решений.
Рефакторинг ваших классов, чтобы избежать самостоятельного вызовавызовы, которые обходят прокси.
Документация Spring описывает это как «Лучший подход (здесь термин« лучший »используется свободно)» .
ПреимуществаЭтот подход заключается в его простоте и отсутствии каких-либо связей с какой-либо структурой.Тем не менее, это может не подходить для очень транзакционной тяжелой базы кода, так как в результате вы получите множество тривиально небольших классов.
Внутри класса получите ссылку на прокси.
Это можно сделать, внедрив прокси или с помощью жестко закодированного вызова AopContext.currentProxy () (см. Выше документы Spring.).
Этот метод позволяет избежать разделения классов, но во многих отношениях сводит на нет преимущества использования транзакционной аннотации.Мое личное мнение таково, что это одна из тех вещей, которые немного уродливы, но уродство самодостаточно и может быть прагматичным подходом, если используется много транзакций.
Переключитесь на использование AspectJ
Поскольку AspectJ не использует прокси-серверы, самовозврат не является проблемой
Хотя это очень чистый метод - за счет введения другой платформы.Я работал над большим проектом, в котором AspectJ был представлен именно по этой причине.
Не используйте @Transactional вообще
Рефакторинг кода для использования транзакций вручнуюдемаркация - возможно, с использованием шаблона декоратора.
Опция - но та, которая требует умеренного рефакторинга, введения дополнительных рамочных связей и повышенной сложности - поэтому, вероятно, не предпочтительный вариант
My Advice
Обычно разделение кода является лучшим ответом и может также быть полезным для разделения проблем.Однако, если бы у меня была инфраструктура / приложение, которое в значительной степени зависело от вложенных транзакций, я бы подумал об использовании AspectJ, чтобы разрешить собственный вызов.