Spring 3.0 TransactionProxyFactoryBean preInterceptors AfterReturningAdvice无法正常工作

时间:2011-09-13 06:12:41

标签: spring transactions spring-aop

我需要记录业务活动,这些业务活动也可以映射到生成的审计跟踪数据。我使用Hibernate envers作为审计跟踪机制。

我实施活动日志的方式是

  1. 我有使用具体类代理的服务类 (使用CGLIB)并扩展TransactionProxyFactoryBean。这是什么 提供交易方面。
  2. 我的方法要么将基础对象作为活动数据 服务的返回类型或参数。
  3. 假设是当我在上面应用预拦截器时 TransactionProxyFactoryBean ;它的 AfterReturningAdvice 方法 应该在交易完成后调用。
  4. 根据我的理解, TransactionProxyFactoryBean 的前后拦截器应基于拦截器添加到堆栈的假设,表现如下。

    1. 建议方法之前的预拦截器
    2. Spring开始交易
    3. 建议方法之前的拦截器运行
    4. 主要服务方法
    5. 返回建议方法后的拦截器后
    6. Spring提交交易
    7. 返回通知方法后的预拦截器
    8. 然而,当我对应用程序进行去除错误时,我发现在提交事务之前,预拦截器在返回通知方法之后运行

      有人可以指导我做错了什么吗?

      TransactionProxyFactoryBean配置

      <bean id="fqngTransactionManager"
                class="org.springframework.orm.hibernate3.HibernateTransactionManager">
              <property name="sessionFactory">
                  <ref local="sessionFactory"/>
              </property>
          </bean>
      
          <bean id="fqngTxProxyTemplate" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
              <property name="transactionManager"><ref local="fqngTransactionManager"/></property>
              <property name="transactionAttributes">
                    <props>
                        <prop key="save*">PROPAGATION_REQUIRED</prop>
                        <prop key="delete*">PROPAGATION_REQUIRED</prop>
                        <prop key="update*">PROPAGATION_REQUIRED</prop>
                        <prop key="process*">PROPAGATION_REQUIRED</prop>
                        <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
                    </props>
              </property>
          </bean>
      
                 <bean id="activityLogInterceptor"
              class="com.fuelquest.mothra.activitylogs.interceptors.ActivityLogInterceptor">
              <property name="activityLogPostingService">
                  <ref bean="activityLogPostingService" />
              </property>
              <property name="methodList">
                  <list>
                      <value>save*</value>
                      <value>execute*</value>
                      <value>calculate*</value>
                  </list>
              </property>
          </bean>
      

      活动拦截器Java文件定义

      public class ActivityLogInterceptor implements AfterReturningAdvice {
      
          private static final Logger logger = Logger
                  .getLogger(ActivityLogInterceptor.class);
      
          private ActivityLogPostingService activityLogPostingService;
          private List<String> methodList;
      
          @SuppressWarnings("rawtypes")
          @Override
          public void afterReturning(Object returnValue, Method method,
                  Object[] methodParams, Object target) throws Throwable {
              // If return type is ActivityLoggingBaseVO
              if (isLoggedMethod(method.getName())) {
      .......................
      

      服务配置

      <bean id="inventoryControlRuleService" parent="fqngTxProxyTemplate">
                  <property name="target">
                      <bean
                          class="com.fuelquest.mothra.inventorycontrol.service.impl.InventoryControlRuleServiceImpl">
                          <property name="assetService">
                              <ref bean="assetService" />
                          </property>             
                          <property name="pointOfSaleService">
                              <ref bean="pointOfSaleService" />
                          </property>
                          <property name="inventoryService">
                              <ref bean="inventoryService" />
                          </property>
                          <property name="deliveryService">
                              <ref bean="deliveryService" />
                          </property> 
                          <property name="languageCdDao">
                              <ref bean="languageCdDao" />
                          </property>
                          <property name="inventoryBizRulesDao">
                              <ref bean="inventoryBizRulesDao" />
                          </property>
                          <property name="bizRulesResultsDao">
                              <ref bean="bizRulesResultsDao" />
                          </property>
                          <property name="ruleEngineService">
                              <ref bean="ruleEngineService" />
                          </property>
                          <property name="icRuleCalculationDataDao">
                              <ref bean="icRuleCalculationDataDao" />
                          </property>
                          <property name="inventoryControlService">
                              <ref bean="inventoryControlService" />
                          </property>
                          <property name="fqngESBMessagePoster">
                              <ref bean="fqngESBMessagePoster" />
                          </property>
                          <property name="droolsRuleTemplateService">
                              <ref bean="droolsRuleTemplateService" />
                          </property>
                          <property name="uomsDao">
                              <ref bean="uomDao" />
                          </property>
                      </bean>
                  </property>
                  <property name="transactionAttributes">
                      <props>
                          <prop key="calculate*">PROPAGATION_REQUIRED,-Exception</prop>
                          <prop key="execute*">PROPAGATION_REQUIRED,-Exception</prop>
                          <prop key="update*">PROPAGATION_REQUIRED,-Exception</prop>
                          <prop key="f*">PROPAGATION_REQUIRED,readOnly</prop>
                          <prop key="*">PROPAGATION_SUPPORTS</prop>
                      </props>
                  </property>     
                  <property name="preInterceptors">
                      <list>
                          <ref bean="activityLogInterceptor"/>
                      </list>
                  </property>
              </bean>
      

2 个答案:

答案 0 :(得分:1)

我们使用Spring OpenSessionInViewFilter在来自GWT的应用程序/ Web服务器的HTTP线程请求之间共享相同的Hibernate会话。

我们还要求为使用Quartz调度程序启动的cron作业提供Hibernate会话。这些线程无法使用通过OpenSessionInViewFilter提供的Hibernate会话,而我们用于代理事务的TransactionProxyFactoryBean代理失败。因此,我们需要使用额外的org.springframework.aop.framework.autoproxy.BeanNa meAutoProxyCreator来代理轮询和SV规则服务,以便可以从Quartz调度程序中调用它们。

因为我们现在有同一个bean的2个事务代理;具有预拦截器等的Spring功能无法正常工作,因为拦截器应用于使用 BeanNameAutoProxyCreator 而非 TransactionProxyFactoryBean 创建的代理。

解决方案是使用AOP和TX命名空间转移到Spring 2.x事务,这导致创建OpenSessionInViewFilter和Quartz调度程序都使用的单个代理。

答案 1 :(得分:0)

你的理解与我的相符。

会切换到ActivityLogInterceptor帮助的Around建议(MethodInterceptor)吗?如果这样可以解决问题,则可能会报告错误。