事件交互已经成为很多应用程序不可或缺的一部分,Spring框架提供了一个完整的基础设施来处理瞬时事件。下面我们来看看Spring 4.2框架中基于注释驱动的事件监听器。

1、早期的方式

在早期,组件要从Spring事件获知自定义域事件中获取通知,那么组件必须实现ApplicationListener接口并覆写onApplicationEvent方法。

@Component
class OldWayBlogModifiedEventListener implements ApplicationListener<OldWayBlogModifiedEvent> { @Override
public 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();
}
}

2、注释驱动的事件监听器

Spring 4.2框架值得注意的一点,用注释@EventListener注解任意的Spring组件。

@EventListener
public void blogModified(BlogModifiedEvent blogModifiedEvent) {
externalNotificationSender.blogModified(blogModifiedEvent);
}

Spring会为事件创建一个ApplicationListener实例,并从方法参数中获取事件的类型。一个类中被事件注释的方法数量没有限制,所有相关的事件句柄都会分组到一个类中。

3、有条件的事件处理

为了使注释@EventListener的功能更强大,Spring 4.2支持用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;
}
}

要注意,在实际应用中可能不会有本文这样的层次结构的事件。 
还要注意,用Groovy编写会更加简单。

使用条件参数来阐述事件,重要的变化是:

@EventListener(condition = "#blogModifiedEvent.importantChange")
public void blogModifiedSpEL(BlogModifiedEvent blogModifiedEvent) {
externalNotificationSender.blogModifiedSpEL(blogModifiedEvent);
}

4、宽松事件类型的层次结构

Spring 4.2之前的版本,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 = (...); //injected
publisher.publishEvent(new BlogModifiedEvent(blog)); //just plain instance of the event

这一变化使得发布事件更容易。然而另一方面它可以导致事件跟踪变得更加困难,特别是在大型应用程序中。

5、响应发布事件

注释@EventListener还有一点需注意,在非空返回类型时,Spring会自动发布返回的事件。

@EventListener
public BlogModifiedResponseEvent blogModifiedWithResponse(BlogModifiedEvent blogModifiedEvent) {
externalNotificationSender.blogModifiedWithResponse(blogModifiedEvent);
return new BlogModifiedResponseEvent(
blogModifiedEvent.getBlog(), BlogModifiedResponseEvent.Status.OK);
}

6、异步事件处理

注释@EventListener还可以与注释@Async进行组合使用,以提供异步事件处理的机制。下面的代码中,指定的事件监听器既不会阻塞主要的代码执行,又不会被其它的监听器处理。

@Async    //Remember to enable asynchronous method execution
//in your application with @EnableAsync
@EventListener
public void blogAddedAsync(BlogAddedEvent blogAddedEvent) {
externalNotificationSender.blogAdded(blogAddedEvent);
}

为了使工作能够得到异步执行,通常还需在Spring项目的上下文中使用注释@EnableAsync。

  或者xml文件:

<!-- 开启异步调用@Async注解-->
<task:annotation-driven executor="myTaskExecutor"/>
<task:executor id="myTaskExecutor" pool-size="5"/>

7、总结

注释驱动的事件监听器是Spring框架4.2版中引入的新特性,它减少了Spring项目的样板代码,使得代码更加灵活,尤其是在小数量事件的需求时体现更为明显。

Spring 框架中注释驱动的事件监听器详解的更多相关文章

  1. Spring 4.2框架中注释驱动的事件监听器详解

    事件交互已经成为很多应用程序不可或缺的一部分,spring框架提供了一个完整的基础设施来处理瞬时事件.下面我们来看看Spring 4.2框架中基于注释驱动的事件监听器. 1.早期的方式 在早期,组件要 ...

  2. spring框架中AOP思想与各种配置详解

    Spring中提供两种AOP支持:   1.基于代理的经典AOP   2.Aspectj注解配置AOP    首先我们先了解什么是AOP,AOP(Aspect Oriented Programming ...

  3. Spring框架中不同类型的事件

    ContextRefreshedEvent,ApplicationContext初始化或者被更新是会触发,ConfigurableApplicationContext接口中的refresh()方法被调 ...

  4. 在.Net框架中 C# 实现多线程的同步方法详解

    本文主要描述在C#中线程同步的方法.线程的基本概念网上资料也很多就不再赘述了.直接接入主题,在多线程开发的应用中,线程同步是不可避免的.在.Net框架中,实现线程同步主要通过以下的几种方式来实现,在M ...

  5. 项目实践之工作流引擎基本文档!Activiti工作流框架中流程引擎API和服务详解

    流程引擎的API和服务 流程引擎API(ProcessEngine API)是与Activiti打交道的最常用方式 Activiti从ProcessEngine开始.在ProcessEngine中,可 ...

  6. Laravel5.4框架中视图共享数据的方法详解

    本文实例讲述了Laravel5.4框架中视图共享数据的方法.分享给大家供大家参考,具体如下: 每个人都会遇到这种情况:某些数据还在每个页面进行使用,比如用户信息,或者菜单数据,最基本的做法是在每个视图 ...

  7. thinkphp框架中“关联操作”的完整定义详解

    在复杂的关联操作中,如果要给关联定义增加可选的属性,我们可以采用完整定义的方式. 完整定义的格式是: protected $_link = array(     '关联表名1'  =>  arr ...

  8. ssh框架中struts.xml 的配置参数详解

    <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "- ...

  9. Tomcat与Spring中的事件机制详解

    最近在看tomcat源码,源码中出现了大量事件消息,可以说整个tomcat的启动流程都可以通过事件派发机制串起来,研究透了tomcat的各种事件消息,基本上对tomcat的启动流程也就有了一个整体的认 ...

随机推荐

  1. JAVA WEB快速入门之从编写一个基于SpringBoot+Mybatis快速创建的REST API项目了解SpringBoot、SpringMVC REST API、Mybatis等相关知识

    JAVA WEB快速入门系列之前的相关文章如下:(文章全部本人[梦在旅途原创],文中内容可能部份图片.代码参照网上资源) 第一篇:JAVA WEB快速入门之环境搭建 第二篇:JAVA WEB快速入门之 ...

  2. VUE v-for问题

    今天写一个拖动然后使装备交换的功能,在背包格子里 发现直接设置Bags数组的项,v-for渲染出来的列表不会对应改变,只有设置值才会改变 有点拗口,贴代码吧 var repear = this.Bag ...

  3. .NET Framework框架介绍

    1.内容 .net framework c#和.net关系 掌握C#中命名空间2..net 就是微软提供的一个开发平台 版本: vs2008 3.5 vs2010 4.0 vs2012 2013 20 ...

  4. python3爬取网页图片路径并写入文件

    import reimport urllib.request # 获取网页文件def getHtml(url): response = urllib.request.urlopen('https:// ...

  5. php封装生成随机数函数

    随机数函数Random(num,min,max): num:生成的个数 min:最小的数 max:最大的数. <?php //生成随机20个1-80内不重复的随机数 //思路:也没什么思路,就是 ...

  6. 从0到1搭建AI中台

    文章发布于公号[数智物语] (ID:decision_engine),关注公号不错过每一篇干货. 转自 | 宜信技术学院 作者 | 井玉欣 导读:随着“数据中台”的提出和成功实践,各企业纷纷在“大中台 ...

  7. jQuery链式编程

    链式编程 多行代码合并成一行代码,前提要认清此行代码返回的是不是对象.是对象才能进行链式编程 .html(‘val’).text(‘val’).css()链式编程,隐式迭代 链式编程注意:$(‘div ...

  8. DEDE整站动态/静态转换

    方法一:使用DEDE后台的SQL命令行工具 入口:织梦后台-系统-SQL命令行工具 DEDE整站动态化 将所有栏目设置为“使用动态页”: 将所有文档设置为“仅动态”: DEDE整站静态化 将所有栏目设 ...

  9. 1 minute教会你shell

    Shell模板 #!/bin/bash ####################################################### # $Name: shell_template. ...

  10. powershell-脚本运行权限政策

    获取当前策略:Get-ExecutionPolicy 设置当前策略:Set-ExecutionPolicy Unrestricted Restricted——默认的设置, 不允许任何script运行 ...