今天在开发过程中发现一个很奇怪的问题,在模拟事务回滚过程中,发现事务回滚没问题,异常也输出了,但之前配置的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>