1. 程式人生 > >spring中事務和aop的順序問題二(配置形式)

spring中事務和aop的順序問題二(配置形式)

今 天在開發過程中發現一個很奇怪的問題,在模擬事務回滾過程中,發現事務回滾沒問題,異常也輸出了,但之前配置的afterthrowing記錄出錯日誌配 置卻始終不好用,根本不會執行到afterthrowing配置的方法內但afterreturning配置 卻沒有問題,去掉配置的AOP事務後,afterthrowing一切正常。。。仔細想想整個程式執行步驟,考慮到事務的回滾用到的是環繞通知 around,是不是兩個同時執行,log攔截器包含在了事務攔截器裡,所以當事務遇到了錯誤回滾也直接將插入異常日誌一同回滾了?能不能在事務執行遇到 exception回滾以後再去控制它去進入afterthowing配置的方法?於是我又仔細看了看spring 關於aop的配置,驚喜的發現一個"order"引數,這個引數是用來控制aop通知的優先順序,值越小,優先順序越高,於是我手動設定了事務與異常日誌兩個 aop通知的order 引數,控制log攔截器在事務的around之外,不出我所料,問題最終得到解決~~

以下是部分程式碼,可供參考:

<!-- AOP 事務 -->

   <aop:config>
        <aop:pointcut id="serviceMethods"
            expression="execution(* hamob.*.*(..))" />
        <aop:advisor advice-ref="txAdvice"
            pointcut-ref="serviceMethods" order="2"/>
    </aop:config>
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="save*" propagation="REQUIRED" isolation="READ_COMMITTED"/>
         <tx:method name="add*" propagation="REQUIRED" isolation="READ_COMMITTED"/>
         <tx:method name="update*" propagation="REQUIRED" isolation="READ_COMMITTED"/>
         <tx:method name="delete*" propagation="REQUIRED" isolation="READ_COMMITTED"/>
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advice>

<!-- AOP 日誌管理 -->
    <aop:config>
        <aop:aspect ref="logadvice" order="3">
            <aop:pointcut id="logInsertMethods" expression="execution(* hamob.*.save*(..))"/>
            <aop:after-returning method="saveLog" pointcut-ref="logInsertMethods" returning="rvt"/>
        </aop:aspect>
    </aop:config>
    <!-- AOP throwing管理 -->
    <aop:config>
        <aop:aspect ref="logadvice" order="1">
            <aop:pointcut id="throwinglog" expression="execution(* hamob.*.save*(..))"/>
            <aop:after-throwing pointcut-ref="throwinglog" throwing="throwable" method="afterThrowing"/>
        </aop:aspect>
    </aop:config>


在我的程式中,由於用到了hibernate,因此事務註解分佈在各處,結果發現after-throwing無法抓取異常(在指定包名後)。在一個數據庫操作丟擲異常後,事務管理器採取了回滾策略,導致程式丟擲異常後,回滾到事務管理器的處理中,指定包名後更加抓取不到異常了。

<aop:config>
        <aop:aspect ref="exceptionCacher" order="0">
        <aop:pointcut id="performance2" expression="execution(* com.ebupt.justholdon.server..*.*(..))" />
        <aop:after-throwing pointcut-ref="performance2" method="throwExp"  throwing="exp"/>
        </aop:aspect>
 </aop:config>