Spring - @Transactional - Что происходит в фоне?

Только выдайте исключение, если это - действительно ошибка. Если это - ожидаемое поведение для объекта не существовать, возвратите пустой указатель.

Иначе это - вопрос предпочтения.

311
задан ROMANIA_engineer 23 July 2017 в 05:24
поделиться

2 ответа

Это большая тема. Справочный документ Spring посвящает этому несколько глав. Я рекомендую прочитать статьи по Аспектно-ориентированное программирование и Транзакции , так как в основе декларативной поддержки транзакций Spring используется АОП.

Но на очень высоком уровне Spring создает прокси для классы, которые объявляют @Transactional в самом классе или в членах. Прокси-сервер в основном невидим во время выполнения. Он предоставляет Spring способ внедрить поведение до, после или вокруг вызовов методов в объект, к которому выполняется проксирование. Управление транзакциями - лишь один из примеров поведения, которое можно задействовать. Другой пример - проверка безопасности. И вы также можете предоставить свои собственные для таких вещей, как ведение журнала. Поэтому, когда вы аннотируете метод с помощью @Transactional , Spring динамически создает прокси, который реализует тот же интерфейс (интерфейсы), что и класс, который вы аннотируете. И когда клиенты обращаются к вашему объекту, вызовы перехватываются, а поведение вводится через механизм прокси.

Между прочим, транзакции в EJB работают аналогичным образом.

Как вы заметили, механизм посредничества работает только тогда, когда вызовы приходят от какого-то внешнего объекта. Когда вы делаете внутренний вызов внутри объекта, вы действительно делаете вызов через ссылку « this », которая обходит прокси. Однако есть способы обойти эту проблему. Я объясняю один подход в этом сообщении на форуме , в котором я использую BeanFactoryPostProcessor для внедрения экземпляра прокси в классы с «самореференцией» во время выполнения. Я сохраняю эту ссылку в переменной-члене с именем « me ». Затем, если мне нужно выполнить внутренние вызовы, требующие изменения статуса транзакции потока, я направляю вызов через прокси (например, « me.someMethod () »). Сообщение на форуме объясняет более подробно. деталь. Обратите внимание, что код BeanFactoryPostProcessor сейчас будет немного другим, поскольку он был написан еще во временном интервале Spring 1.x. Но, надеюсь, это даст вам представление. У меня есть обновленная версия, которую я, вероятно, смогу сделать доступной.

Обратите внимание, что код BeanFactoryPostProcessor сейчас будет немного другим, поскольку он был написан еще во временном интервале Spring 1.x. Но, надеюсь, это даст вам представление. У меня есть обновленная версия, которую я, вероятно, смогу сделать доступной.

Обратите внимание, что код BeanFactoryPostProcessor сейчас будет немного другим, поскольку он был написан еще во временном интервале Spring 1.x. Но, надеюсь, это даст вам представление. У меня есть обновленная версия, которую я, вероятно, смогу сделать доступной.

243
ответ дан 23 November 2019 в 01:12
поделиться

Когда Spring загружает определения ваших компонентов и настроен на поиск аннотаций @Transactional , он создаст эти прокси-объекты вокруг вашего фактического bean . Эти прокси-объекты являются экземплярами классов, которые автоматически создаются во время выполнения. Поведение по умолчанию этих прокси-объектов при вызове метода - это просто вызвать тот же метод для «целевого» bean-компонента (то есть вашего bean-компонента).

Однако прокси-серверы также могут быть снабжены перехватчиками, и когда они присутствуют, эти перехватчики будут вызываться прокси-сервером до того, как он вызовет метод вашего целевого компонента. Для целевых bean-компонентов, аннотированных @Transactional , Spring создаст TransactionInterceptor и передаст его сгенерированному прокси-объекту. Поэтому, когда вы вызываете метод из клиентского кода, вы вызываете метод прокси-объекта, который сначала вызывает TransactionInterceptor (который начинает транзакцию), который, в свою очередь, вызывает метод вашего целевого bean-компонента. Когда вызов завершается, TransactionInterceptor фиксирует / откатывает транзакцию. Это прозрачно для клиентского кода.

Что касается «внешнего метода», если ваш компонент вызывает один из своих собственных методов, он не будет делать это через прокси. Помните, Spring оборачивает ваш bean-компонент в прокси, ваш bean-компонент не знает об этом. Через прокси проходят только звонки "извне" вашего bean-компонента.

Это поможет?

который, в свою очередь, вызывает метод вашего целевого компонента. Когда вызов завершается, TransactionInterceptor фиксирует / откатывает транзакцию. Это прозрачно для клиентского кода.

Что касается «внешнего метода», если ваш компонент вызывает один из своих собственных методов, он не будет делать это через прокси. Помните, Spring оборачивает ваш bean-компонент в прокси, ваш bean-компонент не знает об этом. Через прокси проходят только звонки "извне" вашего bean-компонента.

Это поможет?

который, в свою очередь, вызывает метод вашего целевого компонента. Когда вызов завершается, TransactionInterceptor фиксирует / откатывает транзакцию. Это прозрачно для клиентского кода.

Что касается «внешнего метода», если ваш компонент вызывает один из своих собственных методов, он не будет делать это через прокси. Помните, Spring оборачивает ваш bean-компонент в прокси, ваш bean-компонент не знает об этом. Через прокси проходят только звонки "извне" вашего bean-компонента.

Это поможет?

тогда он не будет делать это через прокси. Помните, Spring оборачивает ваш bean-компонент в прокси, ваш bean-компонент не знает об этом. Через прокси проходят только звонки "извне" вашего bean-компонента.

Это поможет?

тогда это не будет происходить через прокси. Помните, Spring оборачивает ваш bean-компонент в прокси, ваш bean-компонент не знает об этом. Через прокси проходят только звонки "извне" вашего bean-компонента.

Это поможет?

185
ответ дан 23 November 2019 в 01:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: