Spring AfterReturningAdvice在事务提交之前触发

时间:2012-02-28 15:40:14

标签: wcf spring nhibernate spring.net spring-aop

我似乎遇到了一个奇怪的问题。在我们的服务层,我们使用WCF与nHibernate和Spring.NET 1.3.0.20349。我没有选择将spring升级到下一个版本。

我在具有AfterReturningAdvices的服务上保存方法,这些服务需要进行另一个调用Db的服务调用并使用保存对象的ID。 问题是拦截器在事务提交之前触发,这导致下一个服务调用返回空对象

经过一些阅读,我对弹簧拦截器的理解是:

  1. pre-interceptors beforeadvice方法运行
  2. Spring开始交易
  3. 拦截器之前的运行方法
  4. 主要服务方法
  5. 审讯后的拦截器建议方法
  6. Spring提交交易
  7. 执行
  8. 之后的预审判器

    我的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方法中,我可以在春天之后完成我的工作。 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 个答案:

答案 0 :(得分:1)

通过查看TransactionProxyFactoryObjectAfterPropertySet方法的来源,我认为这实际上是应用建议的顺序。因此,您应该在预拦截器中配置AfterReturningAdvice。 如果没有调用,可能是一个错误,我建议在spring.net forums中询问。

在进行交易时调用的另一种方法是ITransactionSynchronization接口,可以在TransactionSynchronizationManager注册。