【Bug】Spring在一个事物中开启新事物未生效

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/quan20111992/article/details/86814027

先看个缩减版的业务逻辑
在这里插入图片描述
逻辑上要求:当生成业务数据失败时,已落地的数据不可回滚

开发时将 数据落地生成业务数据 这两个处理逻辑放在不同的事物中

@Service("asyncSendMessage")
public class AsyncSendMessageServiceImpl implements SendMessageService{
	
	public Response doAsyncSendMessage(Request<Message> request){
		// do something
		this.indepHandleData(messageBO);
		
		return reponse;
	}

	public void indepHandleData(MessageBO messageBO){
		// handle data
	}
}
<aop:config proxy-target-class="true" >

</aop:config>

<tx:advice id="advice" transaction-manager="transactionManager">
	<tx:attributes>
		<tx:method name="do*" propagation="REQUIRED" read-only="false" />
		<tx:method name="indep*" propagation="REQUIRES_NEW" read-only="false" />
	</tx:attributes>
</tx:advice>

启动项目发现,indepHandleData()doAsyncSendMessage()是在同一个事物中 ( indepHandleData()中抛出异常导致doAsyncSendMessage()中的数据会滚了 )

Spring 的事物实现是通过代理类来实现的,也就是我们调用doAsyncSendMessage()时调用的是代理中的方法,而此时在doAsyncSendMessage内部调用indepHandleData(),则调用的是目标类中的方法,所以无法开启新事物。

为了在调用indepHandleData()时开启新事物,需要调用代理类中的方法而不是目标类中的方法,解决方案有两种:

  1. 重新从Spring容器中获取当前对象
SendMessageService asyncSendMessage = (SendMessageService)SpringUtils.getBean("asyncSendMessage");
asyncSendMessage.indepHandleData(messageBO);
  1. 获取当前代理类对象
<!-- 添加expose-proxy=“true” 暴露当前代理对象 -->
<aop:config proxy-target-class="true" expose-proxy=“true”>

</aop:config>
((SendMessageService)AopContext.currentProxy()).indepHandleData(messageBO)

猜你喜欢

转载自blog.csdn.net/quan20111992/article/details/86814027