侦听127.0.01
介绍
在应用程序内交换事件已成为许多应用程序中必不可少的部分,幸运的是,Spring为瞬态事件(*)提供了完整的基础结构。 最近对事务绑定事件的重构为我提供了一个借口,以在实践中检查Spring 4.2中引入的新的注释驱动事件监听器。 让我们看看可以得到什么。
(*)–对于基于Spring的应用程序中的持续事件, Duramen是一个值得一看的解决方案
旧的方式
要获取有关事件(Spring事件和自定义域事件)的onApplicationEvent
,必须创建一个使用onApplicationEvent
实现ApplicationListener
的组件。
@Component
class OldWayBlogModifiedEventListener implementsApplicationListener<OldWayBlogModifiedEvent> {(...)@Overridepublic void onApplicationEvent(OldWayBlogModifiedEvent event) {externalNotificationSender.oldWayBlogModified(event);}
}
它可以正常工作,但是对于每个事件,都必须创建一个新类来生成样板代码。
另外,我们的事件必须扩展ApplicationEvent
类-Spring中所有应用程序事件的基类。
class OldWayBlogModifiedEvent extends ApplicationEvent {public OldWayBlogModifiedEvent(Blog blog) {super(blog);}public Blog getBlog() {return (Blog)getSource();}
}
请注意 ,在事件中使用域对象有明显的缺点,在许多情况下也不是最好的主意。 代码示例中的伪域对象用于不引入不必要的复杂性。
顺便说一句,在此示例中, ExternalNotificationSender
是类的实例,该类将外部通知发送给注册用户(例如,通过电子邮件,SMS或Slack)。
注释驱动的事件侦听器
从Spring 4.2开始,将收到有关新事件的通知,足以使用@EventListener
注释对任何Spring组件中的方法进行注释。
@EventListenerpublic void blogModified(BlogModifiedEvent blogModifiedEvent) {externalNotificationSender.blogModified(blogModifiedEvent);}
在幕后,Spring将为事件创建一个ApplicationListener
实例,其实例类型取自方法参数。 一类中带注释的方法的数量没有限制-所有相关的事件处理程序都可以分组为一个类。
条件事件处理
为了使@EventListener
更加有趣,可以处理仅满足SpEL编写的给定条件的给定类型的那些事件。 让我们假设以下事件类:
public class BlogModifiedEvent {private final Blog blog;private final boolean importantChange;public BlogModifiedEvent(Blog blog) {this(blog, false);}public BlogModifiedEvent(Blog blog, boolean importantChange) {this.blog = blog;this.importantChange = importantChange;}public Blog getBlog() {return blog;}public boolean isImportantChange() {return importantChange;}
}
请注意,在实际的应用程序中,可能会存在与Blog相关的事件的层次结构。
另请注意,在Groovy中,该类要简单得多。
要仅针对重要更改生成事件,可以使用condition
参数:
@EventListener(condition = "#blogModifiedEvent.importantChange")public void blogModifiedSpEL(BlogModifiedEvent blogModifiedEvent) {externalNotificationSender.blogModifiedSpEL(blogModifiedEvent);}
宽松的事件类型层次结构
从历史上看, ApplicationEventPublisher
仅具有发布在ApplicationEvent之后继承的对象的功能。 从Spring 4.2开始,接口已扩展为支持任何对象类型。 在这种情况下,对象将包装在PayloadApplicationEvent
并通过发送。
//base class with Blog field - no need to extend `ApplicationEvent`
class BaseBlogEvent {}class BlogModifiedEvent extends BaseBlogEvent {}
//somewhere in the code
ApplicationEventPublisher publisher = (...); //injectedpublisher.publishEvent(new BlogModifiedEvent(blog)); //just plain instance of the event
这种变化使发布事件变得更加容易。 但是,另一方面,如果没有内部责任感(例如,针对我们所有域事件的标记接口),则事件跟踪会变得更加困难,尤其是在大型应用程序中。
发布事件以响应
@EventListener
另一个@EventListener
是,在非无效返回类型的情况下,Spring会自动发布返回的事件。
@EventListenerpublic BlogModifiedResponseEvent blogModifiedWithResponse(BlogModifiedEvent blogModifiedEvent) {externalNotificationSender.blogModifiedWithResponse(blogModifiedEvent);return new BlogModifiedResponseEvent(blogModifiedEvent.getBlog(), BlogModifiedResponseEvent.Status.OK);}
异步事件处理
已更新 。 正如RadekGrębski正确建议的那样 ,值得一提的是@EventListener
可以与@Async
批注轻松组合以提供异步事件处理。 特定事件侦听器中的代码不会阻止主代码执行,也不会阻止其他侦听器进行处理。
@Async //Remember to enable asynchronous method execution //in your application with @EnableAsync@EventListenerpublic void blogAddedAsync(BlogAddedEvent blogAddedEvent) {externalNotificationSender.blogAdded(blogAddedEvent);}
为了使其正常工作,通常只需要使用@EnableAsync
在Spring上下文/应用程序中启用异步方法执行@EnableAsync
。
摘要
Spring 4.2中引入的由注释驱动的事件侦听器继续保持减少基于Spring(引导)应用程序中样板代码的趋势。 这种新方法看起来特别有趣,特别是对于事件少,维护费用较低的小型应用程序而言。 在无处不在的Spring(Boot)魔术世界中,更值得记住的是,强大的力量伴随着巨大的责任。
在下一篇博客文章中,我将写出如何将新机制也用于简化事务绑定事件的处理。
请注意 ,Spring Framework 4.2是Spring Boot 1.3的默认依赖项(在编写1.3.0.M5时可用)。 另外,也可以在Gradle / Maven中为Spring Boot 1.2.5手动升级Spring Framework版本–在大多数情况下应该可以使用。
翻译自: https://www.javacodegeeks.com/2015/10/annotation-driven-event-listeners-in-spring-4-2-2.html
侦听127.0.01