介绍

如您可能已经知道的(例如,从我以前的博客文章中 ),不再需要创建一个单独的类,该类使用onApplicationEvent方法实现ApplicationListener以便能够对应用程序事件做出响应(包括来自Spring Framework本身和我们自己的域事件)。 从Spring 4.2开始,添加了对注释驱动的事件侦听器的支持。 在方法级别使用@EventListener就足够了,该方法级别将在@EventListener自动注册相应的ApplicationListener

@EventListenerpublic void blogAdded(BlogAddedEvent blogAddedEvent) {externalNotificationSender.blogAdded(blogAddedEvent);}

请注意 ,在事件中使用域对象有明显的缺点,在许多情况下也不是最好的主意。 代码示例中的伪域对象用于不引入不必要的复杂性。

交易绑定事件

简单紧凑。 对于“标准”事件,一切看起来都很不错,但在某些情况下,需要在事务提交(或回滚)之后执行一些操作(通常是异步操作)。 那是什么 是否可以使用新机制?

业务需求

首先,是一个小题外话-业务需求。 让我们想象一下超级精美的博客聚合服务。 每次添加新博客时都会生成一个事件。 订阅的用户可以接收SMS或推送通知。 可以在将博客对象计划保存在数据库中之后发布该事件。 但是,在提交/刷新失败(违反数据库约束,ID生成器出现问题等)的情况下,整个数据库事务都会回滚。 通知破损的愤怒用户会出现在门口……

技术问题

在现代的事务管理方法中,事务是声明式配置的(例如,使用@Transactional批注),并且在事务作用域的结尾(例如,方法的结尾)触发提交。 总的来说,这非常方便,而且出错的可能性要小得多(与编程方法相比)。 另一方面,提交(或回滚)是在代码外自动完成的,因此我们无法以“经典方式”做出反应(即在调用transaction.commit()之后的下一行中的发布事件)。

老学校实施

不可或缺的Tomek Nurkiewicz提出了Spring的一种可能的解决方案(也是一种非常优雅的解决方案)。 它使用TransactionSynchronizationManager来注册当前线程的事务同步。 例如:

@EventListenerpublic void blogAddedTransactionalOldSchool(BlogAddedEvent blogAddedEvent) {//Note: *Old school* transaction handling before Spring 4.2 - broken in not transactional contextTransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {@Overridepublic void afterCommit() {internalSendBlogAddedNotification(blogAddedEvent);}});}

所传递的代码在Spring事务工作流中的适当位置执行(对于这种情况,“恰好”在提交后执行)。

为了提供对非事务上下文中执行的支持(例如,在不关心事务的集成测试用例中),可以将其扩展为以下形式,以确保不会因java.lang.IllegalStateException: Transaction synchronization is not active而失败java.lang.IllegalStateException: Transaction synchronization is not active异常:

@EventListenerpublic void blogAddedTransactionalOldSchool(final BlogAddedEvent blogAddedEvent) {//Note: *Old school* transaction handling before Spring 4.2//"if" to not fail with "java.lang.IllegalStateException: Transaction synchronization is not active"if (TransactionSynchronizationManager.isActualTransactionActive()) {TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {@Overridepublic void afterCommit() {internalSendBlogAddedNotification(blogAddedEvent);}});} else {log.warn("No active transaction found. Sending notification immediately.");externalNotificationSender.newBlogTransactionalOldSchool(blogAddedEvent);}}

在缺少活动交易的情况下,通过进行此更改,可以立即执行提供的代码。 到目前为止,一切正常,但是让我们尝试在Spring 4.2中使用注释驱动的事件侦听器实现相同的目的。

Spring 4.2+实施

除了@EventListener之外,Spring 4.2还提供了另一个注解@TransactionalEventListener

@TransactionalEventListenerpublic void blogAddedTransactional(BlogAddedEvent blogAddedEvent) {externalNotificationSender.newBlogTransactional(blogAddedEvent);}

执行可以绑定到标准事务阶段:提交之前/之后,回滚之后或完成之后(提交或回滚)。 默认情况下,只有在事件的边界内发布事件时,它才会处理事件。 在其他情况下,该事件将被丢弃。

为了支持在非事务上下文中的执行,可以使用falbackExecution标志。 如果设置为“ true”,则如果没有事务在运行,则将立即处理事件。

@TransactionalEventListener(fallbackExecution = true)public void blogAddedTransactional(BlogAddedEvent blogAddedEvent) {externalNotificationSender.newBlogTransactional(blogAddedEvent);}

摘要

在Spring 4.2中引入的注释驱动的事件侦听器延续了减少基于Spring(Boot)的应用程序中样板代码的趋势。 无需手动创建ApplicationListener实现,无需直接使用TransactionSynchronizationManager只需一个具有正确配置的注释即可。 硬币的另一面是,找到所有事件侦听器会有些困难,尤其是在我们的整体应用程序中有数十个事件侦听器的情况下(尽管可以很容易地对其进行分组)。 当然,新方法仅是一种选择,它在给定的用例中是否有用。 尽管如此,Spring(Boot)的另一个魔力泛滥到了我们的系统中。 但是也许抵抗是徒劳的?

抵抗是徒劳的吗?
资料来源: http : //en.memory-alpha.wikia.com/wiki/Borg_cube

请注意,Spring Framework 4.2是Spring Boot 1.3的默认依赖项(在编写1.3.0.M5时可用)。 另外,可以在Gradle / Maven中为Spring Boot 1.2.5手动升级Spring Framework版本–在大多数情况下它应该可以使用。

  • 可以从GitHub获得代码示例。

顺便说一句,为该博客文章编写示例使我有了使用Spring 4.1中引入的新测试事务管理系统的第一种真正能力(过去,我仅在Spring培训课程中提到过)。 可能,我会尽快写更多有关它的内容。

翻译自: https://www.javacodegeeks.com/2015/10/simpler-handling-of-asynchronous-transaction-bound-events-in-spring-4-2.html

在Spring 4.2中更简单地处理异步事务绑定事件相关推荐

  1. spring3.0异步_在Spring 4.2中更简单地处理异步事务绑定事件

    spring3.0异步 介绍 如您可能已经知道的(例如,从我以前的博客文章中 ),不再需要创建一个单独的类来实现带有onApplicationEvent方法的ApplicationListener , ...

  2. odoo中tree视图上面添加按钮并绑定事件

    原文:https://blog.csdn.net/qq_42832858/article/details/86735745 1.通过qweb模板给相应模块上的tree视图上添加上⾃定义的按钮. 在's ...

  3. Vue中动态加载SVG文件并绑定事件、修改节点数据

    大致的流程是这样的:实现这个需求是首先通过一个工具(drawio)去自定义绘制图形,然后导出一个svg格式的文件,后端搞了一下drawio工具的源码,在导出的时候,为绘制的图形上每个节点都去绑定了一个 ...

  4. 【Java】Spring更简单的读取和存储

    文章目录 Spring更简单的读取和存储对象 1. 存储Bean对象 1.1 前置工作:配置扫描路径 1.2 添加注解存储Bean对象 1.2.1 @Controller(控制器存储) 1.2.2 @ ...

  5. Spring 4.2中由注释驱动的事件侦听器

    介绍 在应用程序内交换事件已成为许多应用程序中必不可少的部分,幸运的是,Spring为瞬态事件(*)提供了完整的基础结构. 最近对事务绑定事件的重构为我提供了一个借口,以在实践中检查Spring 4. ...

  6. jquery unbind 异步_JQuery中绑定事件(bind())和移除事件(unbind())

    有时候事件执行完了,想取消事件的效果可以通过一定的办法来处理.比如bind()(绑定事件)和unbind()(移除通过bind()方法添加的事件)方法来移除事件的效果. 比如下面的一个案例: $(fu ...

  7. Spring更简单的存储对象------不使用XML而使用注解

    1.更简单进行存储: 1.先进行创建Spring的项目 先进行创建maven项目,在pom.xml里面引入对Spring所依赖的jar包(核心包:5.2.3) <!-- https://mvnr ...

  8. Spring Security+Spring Data Jpa 强强联手,安全管理只有更简单!

    Spring Security+Spring Data Jpa 强强联手,安全管理没有简单,只有更简单! 这周忙着更新 OAuth2,Spring Security 也抽空来一篇. Spring Se ...

  9. Spring Security是什么,以及如何在Spring Boot项目中整合Spring Security并且使用它,下面我们通过一个登录案例简单介绍一下Spring Security。

    1.什么是Spring Security? 在了解Spring Security之前,我们是不是应该先思考一个问题,我们自己写的web案例一般都需要先登录,之后登录之后才能访问其他页面,或者说我们不同 ...

最新文章

  1. C++中访问类的私有数据成员的第三种方法
  2. 全麦吐司和普通吐司的区别_全麦面包和普通面包的区别
  3. linux selenium_每天进步一点点 selenium+python
  4. SQL Server 2005合并列成字符串 2008-11-07
  5. oracle的环境配置-基本配置
  6. HTML基础(一):常用标签1
  7. ---M文件-函数式M文件/脚本式、m文件基本构成
  8. MyEclipse 10.7(版本:eclipse 3.7.x-Indigo系列)安装activiti-eclipse-plugin插件(流程设计器)...
  9. 基于ASP.NET技术 学生留言板的设计与实现
  10. 如何下载sci论文?
  11. JAVA学习笔记(七)细胞自动机(带注释)
  12. cuteftp pro 3.2多线程下载导致文件MD5校验值改变
  13. 关于丙类谐振功率放大器的工作原理
  14. Docker 自动启动和容器自动启动
  15. 开源 == 文化:红帽社区开放日图文回顾
  16. 高德GIS地图动态显示打点数据
  17. C++新手,用OOP思想编写的推箱子小游戏,请多赐教
  18. 佳能数码相机照片删除了怎么恢复,如何恢复还原佳能相机误删的照片
  19. 【已解决】Latex如何打出△这个符号
  20. 【python】7-10 将输入的字符串中的字符头尾间隔输出(PTA)

热门文章

  1. 如何封装并发布一个属于自己的ui组件库
  2. 《四世同堂》金句摘抄(十五)
  3. 压力与动力是否成正比?
  4. 我是一位老师,讲课是我的乐趣,可是……
  5. 蓝桥杯JAVA省赛2013-----B------5(有理数类)
  6. c/c++ 字符串分割
  7. SparkSQL中UDAF案例分析
  8. sam+matlab,Sam版Matlab粒子群PSO工具已经更新
  9. 请求对象Request
  10. 测试框架 如何测试私有方法_高效的企业测试–测试框架(5/6)