Как стать автором
Обновить

Комментарии 16

Частный случай первого пункта, аннотация над приватным методом класса, тоже часто встречается.

Проблема может быть решена тремя основными способами:
  1. Самостоятельная инъекция (Self-inject)
  2. Создать еще один уровень абстракции
  3. Использовать TransactionTemplate в методе registerAccount(), обернув вызов createAccount()

Не упомянут один довольно важный и ценный способ решения — перейти в приложении с run-time-weaving на compile-time-weaving. В этом случае вызов аспектов будет встроен прямо в байт-код класса, а не проведён через прокси, как это сделано по умолчанию.


Также compile-time weaving позволяет работать даже аннотациям, которые стоят на методах компонента, не включённых ни в один его интерфейс. Я лично влетал в такую проблему с load-time, когда у меня EventListener'ы не работали из-за этого.

не включённых ни в один его интерфейс

Чтобы такое работало в load-time, достаточно просто включить создание прокси через cglib, а не через стандартный явовский Proxy.

@EnableAspectJAutoProxy(proxyTargetClass = true)

Да, сама проблема в статье это следствие использования Java Proxy. И compile-time weaving, и cglib проблемы такой не имеют, потому что оба встраивают вызов аспектов в байт-код. Только один в рантайме, а второй при компиляции.

Зачем тогда по-умолчанию используется Java Proxy?

Это мне неведомо, но предположительно из-за меньшей инвазивности в процесс сборки проекта.

У Java пока что нет нормального ClassFile API, который был бы относительно стабилен между версиями, а существующее байтоложество - штука достаточно хрупкая, хотя за годы развития отлажена стала неплохо. Proxy, при этом - стабилен, включён в JDK, и позволяет удовлетворительно закрыть множество сценариев использования аннотаций. Особенно в комбинации с анализаторами типа Sonar, которые будут бить по рукам и напоминать.

А если класс не реализует никакой интерфейс как в примере, то такой проблемы не возникает при вызове снаружи класса? То есть если класс реализует какой-то интерфейс, то при вызове снаружи класса метода (который не объявлен в интерфейсе) с аннотацией transaction, эта аннотация не сработает?

Также compile-time weaving позволяет работать даже аннотациям, которые стоят на методах компонента, не включённых ни в один его интерфейс

Если интерфейсов нет, то будет откат к генерации класса через CGLIB.

То есть если класс реализует какой-то интерфейс, то при вызове снаружи класса метода (который не объявлен в интерфейсе) с аннотацией transaction, эта аннотация не сработает?

Сначала хотел ответить будто знаю, как он себя поведёт - но в итоге понял, что не знаю, и надо будет экспериментировать с этим.

Точно знаю, что пару лет назад декларации @EventListener требовали наличия их в интерфейсе, так как для их работы было нужно, чтобы прокси-класс при просмотре через рефлексию возвращал соответствующие методы, а он сможет это делать только если они были в его родительских интерфейсах. У меня не было похожих проблем с @Transactional , но и ситуации, когда имеется помеченный метод, не входящий в какой-либо интерфейс не было тоже.

Даже для @EventListener это поведение, в принципе, с того времени могло измениться, хотя для такого старого компонента системы шансы на это мизерные.

>>Различные механизмы распространения помогают связать транзакции в нашей бизнес-логике. Например, если вам нужно запустить какой-то код в другой транзакции, а не во внешней, можно использовать распространение REQUIRES_NEW, которое приостанавливает внешнюю транзакцию, создает новую, а затем возобновляет внешнюю транзакцию.

REQUIRES_NEW ничего не "приостанавливает" - вы из одного потока управления стратанули 2 транзакции, можете стартануть 3, 4 и так далее - это все будут активные транзакции созданные в одном потоке. Схема скорее походит на ChainedTransactionManager с той лишь разницой что у всех транзакций один и тот же TransactionManager

А как на уровне СУБД это выглядит?

как несколько независимых транзакций

В разных connection?

Да, конечно - это все будут разные connection'ы

А вы сами ссылку на bitronix, которую даёте, открывали? Из современных поддерживаемых проектов narayana есть.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий