记一个日志切面及事务传播的问题

被这问题搞了一下午。

背景:

有一个接口方法,添加了事务注解,简化后大概长这样:
在这里插入图片描述
这个方法可能会抛出异常;
然后还有个日志切面,环绕这个接口,大概长这样:
在这里插入图片描述

需求:

目标方法正常执行成功,提交事务,正常返回;如果出现异常,回滚,向上抛出异常;
日志切面记录目标方法的调用记录,不管目标方法是否正常都应正常记录,且日志记录不应影响到主流程。

问题:

单元测试时,调用这个目标方法出现异常了,目标理应回滚,日志理应仍被记录;但是发现没有回滚,新建订单成功入库了,日志也被记录了。
发现是 日志的切面和目标方法事务的切面发生了事务传播;
后面我就把事务范围给缩小了,目标方法就可以正常回滚了。大概长这样:
在这里插入图片描述
用这种方式需要再启动类上加上: @EnableAspectJAutoProxy(exposeProxy = true)
为什么可以请自行搜索。

介绍另一种缩小事务范围的方式:编程式事务
1)先注入 TransactionTemplate ,这个类直接注入就行,spring已经自动把它配置成bean了

	@Autowired
    private  TransactionTemplate transactionTemplate;

2)使用

transactionTemplate.execute(status -> {
    // 做一些事
    //最后返回值可以 是做的事情的返回值,如果不需要返回值,任意返回个什么都行
    return Boolean.TRUE;
});

上面2步就完成了编程式事务,只对着一部分代码做事务控制,看下面spring的源码,只有系统里面没有,就会配置这个bean
在这里插入图片描述

到此事务的问题解决了;

然后有发现一个新的问题;
我外面调这个目标接口是需要获取正常的返回值,或者是抛出的异常的;
但是因为这个切面把异常catch掉了,所以只能要么正常返回,要么出异常了返回null,
所以又对切面进行了一下改造,大概长这样:
在这里插入图片描述
经测试可以满足我的需求。

之前在解决第一个问题时又试过这样在切面里面再抛异常,但是这样会导致记录日志也被回滚。
记录日志不能影响正常业务流程,所以在记录日志的insert需要try一下,不然记录日志出错,主流程也GG了

总结:

1.我的做法是缩小目标方法的事务范围,保证目标方法能正常处理事务而不被日志切面影响;
2.日志切面中如果目标方法抛出了异常就继续向上抛,同时日志切面用finally来保证日志始终都会被记录;
3.记录日志时再单独对记录方法try-catch,保证日志记录不会影响到主流程。

问题解决后又去网上搜了一些类似问题的解决方案,还真发现了不少。

比如更改切面执行顺序、更改事务传播方式 … 可以解决事务传播的问题等等

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值