Spring AfterReturningAdvice срабатывает до совершения транзакции - PullRequest
3 голосов
/ 28 февраля 2012

Кажется, у меня странная проблема.На уровне сервисов мы используем WCF с nHibernate и Spring.NET 1.3.0.20349.У меня нет возможности обновить spring до следующей версии.

У меня есть методы сохранения в службе, которая имеет AfterReturningAdvices, которые необходимы для выполнения другого вызова службы, который вызывает в БД и использует идентификаторсохраненный объект Проблема в том, что перехватчик срабатывает до совершения транзакции, что вызывает следующий вызов службы для возврата пустых объектов

После некоторого чтения мое понимание перехватчиков Springs таково:

  1. Методы предварительного перехватчика перед обслуживанием запускаются
  2. Spring запускает транзакцию
  3. Методы предварительного перехватчика перед обслуживанием запускаются
  4. Основной метод обслуживания запускается
  5. Выполнение методов рекомендаций после возврата перехватчиков
  6. Spring фиксирует транзакцию
  7. Методы рекомендаций после возврата перехватчиков выполняется

Мой web.config имеет следующее:

  <object id="InsertPointcut" type="Spring.Aop.Support.NameMatchMethodPointcutAdvisor, Spring.Aop">
    <property name="advice">
      <ref local="afterAddInterceptor"/>
    </property>
    <property name="MappedNames">
      <list>
        <value>AddToEvent</value>
      </list>
    </property>
  </object>

  <object id="UpdatePointcut" type="Spring.Aop.Support.NameMatchMethodPointcutAdvisor, Spring.Aop">
    <property name="advice">
      <ref local="afterUpdateInterceptor"/>
    </property>
    <property name="MappedNames">
      <list>
        <value>Update</value>
      </list>
    </property>
  </object>
      <object id="ServiceProxy" type="Spring.Transaction.Interceptor.TransactionProxyFactoryObject, Spring.Data">
    <property name="PlatformTransactionManager" ref="transactionManager"/>
    <property name="TransactionAttributeSource" ref="attributeTransactionAttributeSource"/>
    <property name="target">
      <object id="Service" type="Service, Service" init-method="init">
        <constructor-arg ref="sessionFactory" />
        <property name="EventRepository" ref="eventRepository" />
      </object>
    </property>
    <property name="preInterceptors">
      <list>
        <ref local="throwsAdvice"/>
        <ref local="InsertPointcut"/>
        <ref local="UpdatePointcut"/>
      </list>
    </property>       
  </object>

Кто-нибудь может помочь?

[Обновление]

Чтобы не вносить изменения в код в моих службах, я реализовал Интерфейс ITransactionSynchronization по моему совету и зарегистрировал его.Таким образом, в методе AfterCompletion я могу выполнять свою работу после того, как выполнено spring & nHibernate.Я не уверен, что есть лучший способ справиться с этим, но, похоже, он работает.

 public class AfterUpdateInterceptor : IAfterReturningAdvice, ITransactionSynchronization
{
    private int id;
    [Transaction]
    public void AfterReturning(object returnValue, MethodInfo method, object[] args, object target)
    {
        TransactionSynchronizationManager.RegisterSynchronization(this);
        if (args == null || args.Length == 0)
        {
            return;
        }

        id = PropertyHelper.GetIdPropertyValue<IUpdateContract>(args);
    }

    public void Suspend()
    {
    }

    public void Resume()
    {
    }

    public void BeforeCommit(bool readOnly)
    {
    }

    public void AfterCommit()
    {
    }

    public void BeforeCompletion()
    {
    }

    public void AfterCompletion(TransactionSynchronizationStatus status)
    {
        if (status != TransactionSynchronizationStatus.Committed) return;//.com msg not sent.

        if (id > 0)
        {
            XmlSender.SendXmlUpdate(MessageType.Update, id);
        }
        id = 0;
    }
}

1 Ответ

1 голос
/ 29 февраля 2012

Посмотрев на источник TransactionProxyFactoryObject * AfterPropertySet, я думаю, что на самом деле это порядок примененных советов.Таким образом, вы должны иметь AfterReturningAdvice, настроенный в ваших пре-перехватчиках.Если это не называется, это может быть ошибка, и я бы посоветовал спросить на spring.net форумах .

Другим способом вызова при завершении транзакции является интерфейс ITransactionSynchronization , который можно зарегистрировать с помощью TransactionSynchronizationManager.

...