Spring Event 事件中的事务控制

Spring Event 可以简单实现业务解耦,从Spring 4.2以后,事件处理不用实现ApplicationListener 的 onApplicationEvent方法了,使用注解@EventListener可以自动关联相关的ApplicationListener

    @EventListener(condition = "#event.shouldSendMsg")
    public void afterRegisterSendMail(MessageEvent event) {
         mailService.send(event.getUser().getEmail(),"register successful");
    }

事务绑定事件

标准的事件模型在一些业务上能很好的满足需求,例如异步化处理,不干扰主线程执行等,不论事务被提交或回滚,都能正常执行.但是如果我们只是希望事务被提交后,再执行事件呢?

例如,用户注册成功后添加一个发送邮件的事件,或者推送消息,或者短信,这时候需要保存数据库后,再进行这些操作.但是万一事务提交失败数据库事务会回滚,这时候如果用户收到邮件,那可惨淡了!

在Spring事务管理中, 事务是配置注解声明的 (@Transactional) 提交操作将在方法结束后执行. 提交是自动自行的(transaction.commit()). 以下是一些解决方式:

解决方案1(<Spring 4.2):

@EventListener
public void afterRegisterSendMail(MessageEvent event) {
    // Spring 4.2 之前
 
    TransactionSynchronizationManager.registerSynchronization(
            new TransactionSynchronizationAdapter() {
                @Override
                public void afterCommit() {
                    internalSendMailNotification(event);
                }
            });
}

上面的代码将在事务提交后执行.如果在非事务context中将抛出java.lang.IllegalStateException: Transaction synchronization is not active,

	@EventListener
		public void afterRegisterSendMail(MessageEvent event) {
		    // Spring 4.2 之前
		 
		    if (TransactionSynchronizationManager.isActualTransactionActive()) {
		 
		        TransactionSynchronizationManager.registerSynchronization(
		                new TransactionSynchronizationAdapter() {
		                    @Override
		                    public void afterCommit() {
		                    	mailService.send(event);
		                    }
		                });
		    } else {
		        mailService.send(event);
		    }
		}

这样无论是否有事务都能兼容啦. 下面介绍Spring 4.2以后的简化处理:

解决方案2(Spring 4.2 +)

Spring 4.2除了EventListener之外,额外提供了新的注解TransactionalEventListener

	    @TransactionalEventListener
		public void afterRegisterSendMail(MessageEvent event) {
			mailService.send(event);
		}

这个注解的强大之处在于可一直控制事务的 before/after commit, after rollback ,after completion (commit或 rollback). 默认情况下,在事务中的Event将会被执行,其他情况不触发.

在非事务context下,如果也想执行,启用参数:fallbackExecution=true,

	    @TransactionalEventListener(fallbackExecution = true)
		public void afterRegisterSendMail(MessageEvent event) {
			mailService.send(event);
		}

 

https://my.oschina.net/osgit/blog/883823

转载于:https://my.oschina.net/osgit/blog/883823

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值