事件交互已经成为很多应用程序不可或缺的一部分,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. Redis原理及使用

    一:原理介绍 1:什么是redis?  Redis 是一个基于内存的高性能key-value数据库. 2:Reids的特点Redis本质上是一个Key-Value类型的内存数据库,很像memcache ...

  2. C#实现.ini文件读写操作

    1.ini文件是什么?        见百度百科:https://baike.baidu.com/item/ini%E6%96%87%E4%BB%B6/9718973?fr=aladdin 2.C#语 ...

  3. 微信小程序性能优化之一

    性能优化 界面和业务逻辑之间事件交互小程序调用nativeNative回调小程序 图片源文件优化 渲染优化 ---------------------------------------------- ...

  4. Struts2笔记_拦截器

    A.拦截器是什么 --- Interceptor:拦截器,起到拦截Action的作用. ---Filter:过滤器,过滤从客户端向服务器发送的请求. ---Interceptor:拦截器,拦截是客户端 ...

  5. Gerrit系统框架介绍

    Gerrit目录介绍 转自:https://blog.csdn.net/tanshizhen119/article/details/79889242 先上图 bin/ : 主要是放gerrit.sh启 ...

  6. .net 笔试面试总结(1)

    趁着在放假时候,给大家总结一点笔试面试上的东西,也刚好为年后跳槽做一点小积累. 下面的参考解答只是帮助大家理解,不用背,面试题.笔试题千变万化,不要梦想着把题覆盖了,下面的题是供大家查漏补缺用的,真正 ...

  7. python3 Flask -day4 自定义url转换器

    url传参可以限定参数的数据类型,例如:限定user_id数据类型为int @app.route('/user/<int:user_id>') def my_list(user_id): ...

  8. 小程序中使用ECharts 异步加载数据

    官网例子都是同步的,怎么引入及同步demo请移步官网 <view class="container"> <ec-canvas id="mychart-d ...

  9. PHP制作个人博客-广告位添加与调用 推荐文章数据调取

    上一节博客的导航我们已经动态调取,这一节我们主讲一下如何根据页面布局,后台添加广告位,及模板上动态调取广告.博客推荐文章的数据调用. 首先我们在云码博客的后台添加10条左右的测试数据,thinkcmf ...

  10. appium+python搭建自动化测试框架_TestAPP框架(三)

    Pycharm 创建 Project,搭建 APPTEST框架如下图:   1.框架功能 业务功能的封装 测试用例封装 测试包管理 截图处理 断言处理 日志获取 测试报告生成 数据驱动 数据配置 2. ...