java - transaction - tx:annotation-driven




[email protected]Что происходит в фоновом режиме? (3)

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

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

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

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

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

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


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

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

(Мне разрешили опубликовать фотографию при условии, что я упомянул ее истоки. Автор: Ноэль Вайс, сайт: www.noelvaes.eu)


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

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

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

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


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

Если вы используете вызов JPA, то все транзакции находятся на этой границе транзакции. Допустим, вы сохраняете объекты entity1, entity2 и entity3. Теперь, сохраняя сущность3, возникает исключение, так как enitiy1 и entity2 входят в одну транзакцию, поэтому entity1 и entity2 будут откатами с сущностью3.

Транзакция: (entity1.save, entity2.save, entity3.save). Любое исключение приведет к откату всех транзакций JPA с БД. Внутренняя транзакция JPA используется весной.





transactional