Вопрос

Я хочу знать, что на самом деле происходит, когда вы аннотируете метод с @Transactional? Конечно, я знаю, что пружина завершит этот метод в транзакцию.

Но у меня есть следующие сомнения:

  1. Я слышал, что весна создает прокси -класс? Может кто -нибудь объяснить это больше глубина. Что на самом деле находится в этом классе по доверенности? Что происходит с фактическим классом? И как я могу увидеть созданный прокси -класс Spring
  2. Я также читаю в весенних документах, что:

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

Источник: http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html

Почему только внешние вызовы метода будут находиться в рамках транзакции, а не методов самостоятельного вознаграждения?

Это было полезно?

Решение

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

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

Кстати, транзакции в EJB работают так же.

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

Другие советы

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

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

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

Это помогает?

Как визуальный человек, мне нравится весить с диаграммой последовательности прокси -паттерна. Если вы не знаете, как читать стрелы, я прочитал первый как это: Client выполняет Proxy.method().

  1. Клиент вызывает метод с целью с точки зрения и молча перехвачен прокси -сервером
  2. Если аспект определен, прокси выполнит его
  3. Затем выполняется фактический метод (цель)
  4. После возврата и послеоходов-дополнительные аспекты, которые выполняются после возврата метода и/или, если метод бросает исключение
  5. После этого прокси выполняет аспект после
  6. Наконец прокси возвращается к клиенту вызывающего

Proxy Pattern Sequence Diagram(Мне было разрешено опубликовать фотографию при условии, что я упомянул ее происхождение. Автор: Ноэль Vaes, веб -сайт: www.noelvaes.eu)

Самый простой ответ - это, На каком методе вы объявляете @Transactional, граница транзакции запускается, а граница заканчивается, когда метод завершается.

Если вы используете вызов JPA, то все коммиты находятся в этой границе транзакции. Допустим, вы спасаете Entity1, Entity2 и Entity3. Теперь, когда Saving Entity3 происходит исключение, тогда как enitiy1 и entity2 выступают в той же транзакции, поэтому Entity1 и Entity2 будут откатами от Entity3.

Транзакция: (Entity1.save, Entity2.save, Entity3.save). Любое исключение приведет к откату от всех транзакций JPA с DB. Внутренняя транзакция JPA используется к весне.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top