文章链接:https://liuyueyi.github.io/hexblog/hexblog/2018/06/09/180609-Spring之事件驱动机制的简单使用/

Spring之事件驱动机制的简单使用

关于事件的发起与相应,在客户端的交互中可算是非常频繁的事情了,关于事件的发布订阅,在Java生态中,EventBus可谓是非常有名了,而Spring也提供了事件机制,本文则主要介绍后端如何在Spring的环境中,使用事件机制

I. 使用姿势

主要借助org.springframework.context.ApplicationEventPublisher#publishEvent(org.springframework.context.ApplicationEvent) 来发布事件,而接受方,则直接在处理的方法上,添加 @@EventListener注解即可

1. 事件定义

发布一个事件,所以第一件事就是要定义一个事件,对Spring而言,要求自定义的事件继承自ApplicationEvent类, 一个简单的demo如下

public class NotifyEvent extends ApplicationEvent {
@Getter
private String msg; public NotifyEvent(Object source, String msg) {
super(source);
this.msg = msg;
}
}

2. 发布事件

发布时间则比较简单,直接拿到ApplicationContext实例,执行publish方法即可,如下面给出一个简单的发布类

@Component
public class NotifyPublisher implements ApplicationContextAware {
private ApplicationContext apc; @Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.apc = applicationContext;
} // 发布一个消息
public void publishEvent(int status, String msg) {
if (status == 0) {
apc.publishEvent(new NotifyEvent(this, msg));
} else {
apc.publishEvent(new NewNotifyEvent(this, msg, ((int) System.currentTimeMillis() / 1000)));
}
}
}

3. 事件监听器

在方法上添加注解即可,如下

@Component
public class NotifyQueueListener { @EventListener
public void consumerA(NotifyEvent notifyEvent) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("A: " + Thread.currentThread().getName() + " | " + notifyEvent.getMsg());
} @EventListener
public void consumerB(NewNotifyEvent notifyEvent) {
System.out.println("B: " + Thread.currentThread().getName() + " | " + notifyEvent.getMsg());
} @EventListener
public void consumerC(NotifyEvent notifyEvent) {
System.out.println("C: " + Thread.currentThread().getName() + " | " + notifyEvent.getMsg());
}
}

II. 疑问及解答

1. 发布与监听器的关联

上面给出了使用的姿势,看起来并不复杂,也比较容易使用,但是一个问题需要在使用之前弄明白了,发布事件和监听器是怎么关联起来的呢?

  • 根据方法的参数类型执行

那么如果发布者,推送的是一个NotifyEvent类型的事件,那么接收者是怎样的呢?

  • 参数为NotifyEvent以及其子类的监听器,都可以接收到消息

测试用例如下:

NewNotifyEvent 继承自上面的NotifyEvent

public class NewNotifyEvent extends NotifyEvent {
@Getter
private int version; public NewNotifyEvent(Object source, String msg) {
super(source, msg);
}
public NewNotifyEvent(Object source, String msg, int version) {
super(source, msg);
this.version = version;
}
}

然后借助上面的消息发布者发送一个消息

@Test
public void testPublishEvent() throws InterruptedException {
notifyPublisher.publishEvent(1, "新的发布事件! NewNotify");
System.out.println("---------");
notifyPublisher.publishEvent(0, "旧的发布事件! Notify");
}

输出结果如下,对于NewNotifyEvent, 参数类型为NotifyEvent的consumerA, consumerC都可以接收到

A: main | 新的发布事件! NewNotify
C: main | 新的发布事件! NewNotify
B: main | 新的发布事件! NewNotify
---------
A: main | 旧的发布事件! Notify
C: main | 旧的发布事件! Notify

2. 消息接收的顺序

上面消息处理是串行的,那么先后顺序怎么确定? (下面的答案不确定,有待深入源码验证!!!)

  • 先扫描到的bean先处理
  • 同一个bean中,按精确匹配,先后定义顺序进行

3. 异步消费

对于异步消费,即在消费者方法上添加一个@Async注解,并需要在配置文件中,开启异步支持

@Async
@EventListener
public void processNewNotifyEvent(NewNotifyEvent newNotifyEvent) {
System.out.println("new notifyevent: " + newNotifyEvent.getMsg() + " : " + newNotifyEvent.getVersion());
}

配置支持

@Configuration
@EnableAsync
public class AysncListenerConfig implements AsyncConfigurer {
/**
* 获取异步线程池执行对象
*
* @return
*/
@Override
public Executor getAsyncExecutor() {
return new ThreadPoolExecutor(5, 10, 1, TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>(),
new DefaultThreadFactory("test"), new ThreadPoolExecutor.CallerRunsPolicy());
}
}

III. 其他

一灰灰Bloghttps://liuyueyi.github.io/hexblog

一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛

声明

尽信书则不如,已上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激

扫描关注

180609-Spring之事件驱动机制的简单使用的更多相关文章

  1. 简单说说spring的事务机制,以及是如何管理的?

    事务管理可以帮助我们保证数据的一致性,对应企业的实际应用很重要. Spring的事务机制包括声明式事务和编程式事务. 编程式事务管理:Spring推荐使用TransactionTemplate,实际开 ...

  2. Spring Event事件驱动

    Spring事件驱动模型,简单来说类似于Message-Queue消息队列中的Pub/Sub发布/订阅模式,也类似于Java设计模式中的观察者模式. 自定义事件 Spring的事件接口位于org.sp ...

  3. JS事件驱动机制

    还记得当初学JAVA-GUI编程时学习过事件监听机制,此时再学习JavaScript中的事件驱动机制,不免简单.当初学习时也是画过原理图,所以从原理图开始吧! js是采用事件驱动(event-driv ...

  4. Nginx——事件驱动机制(雷霆追风问题,负载均衡)

    事件处理框架 所有的worker进程都在ngx_worker_process_cycle方法中循环处理事件,处理分发事件则在ngx_worker_process_cycle方法中调用ngx_proce ...

  5. Spring事务传播机制和数据库隔离级别

    Spring事务传播机制和数据库隔离级别 转载 2010年06月26日 10:52:00 标签: spring / 数据库 / exception / token / transactions / s ...

  6. 【转】Java异常总结和Spring事务处理异常机制浅析

    异常的概念和Java异常体系结构 异常是程序运行过程中出现的错误.本文主要讲授的是Java语言的异常处理.Java语言的异常处理框架,是Java语言健壮性的一个重要体现. Thorwable类所有异常 ...

  7. 7 -- Spring的基本用法 -- 3... Spring 的核心机制 : 依赖注入

    7.3 Spring 的核心机制 : 依赖注入 Spring 框架的核心功能有两个. Spring容器作为超级大工厂,负责创建.管理所有的Java对象,这些Java对象被称为Bean. Spring容 ...

  8. Java异常总结和Spring事务处理异常机制浅析

    异常的概念和Java异常体系结构 异常是程序运行过程中出现的错误.本文主要讲授的是Java语言的异常处理.Java语言的异常处理框架,是Java语言健壮性的一个重要体现. Thorwable类所有异常 ...

  9. Redis源代码解析:13Redis中的事件驱动机制

    Redis中.处理网络IO时,採用的是事件驱动机制.但它没有使用libevent或者libev这种库,而是自己实现了一个很easy明了的事件驱动库ae_event,主要代码只400行左右. 没有选择l ...

随机推荐

  1. C#string byte[] base64位互相转换

    byte表示字节,byte[]则表示存放一系列字节的数组 1个字符=2个字节(byte) 1个字节=8个比特(bit) 网速上所说的1M其实是指1兆的小b,1M= 1024b/8 = 128kb 下面 ...

  2. PAT——不吉利的日期(java中date和Calendar使用)

    题目描述 在国外,每月的 13 号和每周的星期 5 都是不吉利的.特别是当 13 号那天恰好是星期 5时,更不吉利. 现在给你一个年份,请你从小到大依次输出当年所有13 号是星期 5 的月份. 输入描 ...

  3. Python入门基础:代码的编码风格

    每种语言都有自己的编码风格,对于Python这种比较注重于空格的影响的代码而言,其风格也是相当重要的. 主要包括以下几点: 1:使用 4 空格缩进,而非 TAB  .在小缩进(可以嵌套更深)和大缩进( ...

  4. POJ 3984 迷宫问题(简单bfs+路径打印)

    传送门: http://poj.org/problem?id=3984 迷宫问题 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions ...

  5. HDU 2080(三角函数)

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=2080 夹角有多大II Time Limit: 1000/1000 MS (Java/Others)    ...

  6. 解决Windows10下小娜无法搜索本地应用的问题

    适用场景 小娜突然出现各种问题.比如突然无法搜索到本地应用...等其它问题 一般使用下面的方法,将小娜进行重新注册就ok了. 解决方案 1.用管理员权限打开 C:\Windows\System32\W ...

  7. iOS:URL Scheme(完结)(18-1-3更)

    1.APP跳转 2.APP功能跳转 3.系统功能跳转 1.APP跳转 1.被打开方 设置APP的URL Types(设置位置在 “项目 - TARGETS - APP icon - info - (拉 ...

  8. 如何编写及运行JS

    JS也是一种脚本语言,他可以有两种方式在HTML页面进行引入,一种是外联,一种是内部.       外联JS的写法为: <script src="相对路径"></ ...

  9. Zabbix——设置模板

    前提条件: Zabbix版本为4.0 可以正常使用Server 1. 添加H3C网络交换机的CPU和内存模板,并配置自动发现. 注意,需要添加完成后,重新进行搜索后再此进入才有下列选项. 添加CPU的 ...

  10. linux ping命令实践

          ping 解析       Linux系统的ping命令是常用的网络命令,它通常用来检测与目标主机的连通性,经常说"ping以下机器,看是否开着,不能打开网页时候,可以ping ...