springboot 中事件监听模型的一种实现
前言: 事件监听模型是一种常用的设计模式,在springboot 中我们如何实现呢?
首先我们要理解事件监听中需要的几个角色
- 事件发布者 (即事件源)
- 事件监听者
- 事件本身
废话不多说直接上代码
定义事件本身
事件本身需要继承ApplicationEvent
package com.yxd;
import java.util.List;
import java.util.Map;
import org.springframework.context.ApplicationEvent;
public class DemoEvent extends ApplicationEvent{
private String type;
private List<Map> msg;
public DemoEvent(Object object, String type ,List<Map> msg) {
super(object);
this.msg = msg;
this.type = type;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public List<Map> getMsg() {
return msg;
}
public void setMsg(List<Map> msg) {
this.msg = msg;
}
}
如图:

定义事件源
事件源需要注入 **ApplicationContext **
package com.yxd;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
@Component
public class DemoPublisher {
@Autowired
ApplicationContext applicationContext;
public void publish(DemoEvent event) {
applicationContext.publishEvent(event);
}
}
定义监听者
监听者有两种实现
一、需要实现 ApplicationListener
package com.yxd;
import java.util.List;
import java.util.Map;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Component
public class DemoListener1 implements ApplicationListener<DemoEvent> {
@Override
public void onApplicationEvent(DemoEvent event) {
List<Map> msg = event.getMsg();
String type = event.getType();
System.out.println(" listener1接收到了 publisher 发送的消息 , 时间 "+ Time.getTime());
System.out.println("listener1 : 类型 :" + type +", 消息内容: " + msg + ", 消息处理完毕! "+ Time.getTime());
}
}
二、使用 @EventListener 注解
package com.yxd;
import java.util.List;
import java.util.Map;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
public class DemoListener2 {
@EventListener
public void onDemoEvent(DemoEvent demoEvent) {
System.out.println(" listener2 通过注解接收到了 publisher 发送的消息 , 时间 "+ Time.getTime());
List<Map> msg = demoEvent.getMsg();
String type = demoEvent.getType();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("listener2 : 类型 :" + type +", 消息内容: " + msg + ", 消息处理完毕! "+ Time.getTime());
}
}
此处我们还需要注意一点,此处多个监听是同步执行的(阻塞),一般情况下我们发布一个事件,是不关心谁来处理,以及处理结果的,所以我们还需要加上异步的注解
package com.yxd;
import java.util.List;
import java.util.Map;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@Component
public class DemoListener3 implements ApplicationListener<DemoEvent> {
@Override
@Async
public void onApplicationEvent(DemoEvent event) {
System.out.println(" listener3 接收到了 publisher 发送的消息 , 时间 "+ Time.getTime());
List<Map> msg = event.getMsg();
String type = event.getType();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("listener3 异步执行:类型 :" + type +", 消息内容: " + msg+ ", 消息处理完毕! "+ Time.getTime());
}
}
测试
package com.yxd;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@EnableAsync
@SpringBootApplication
@RestController
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Autowired
DemoPublisher demoPublisher;
@RequestMapping("testListener")
public String testListener() {
ArrayList<Map> list = new ArrayList<>();
HashMap<String, String> m1 = new HashMap<>();
m1.put("1", "2");
HashMap<String, String> m2 = new HashMap<>();
m2.put("3", "4");
HashMap<String, String> m3 = new HashMap<>();
m3.put("5", "6");
list.add(m1);
list.add(m2);
list.add(m3);
System.out.println("开始发布消息: " + Time.getTime());
demoPublisher.publish(new DemoEvent(this,"测试消息",list));
System.out.println("消息发布结束: " + Time.getTime());
return "消息发布成功";
}
}
我们访问接口


三个监听者都得到了消息。。
但是 listener2 通过注解 先得到了消息,延时2秒后,listener1 才得到消息,listener1 处理完后,主线程继续执行,同时listener3 开始接收到消息,开启了一个异步任务,3秒后执行结束
项目结构

最后附上Time类
package com.yxd;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Time {
public static String getTime() {
return new SimpleDateFormat("HH:mm:ss").format(new Date());
}
}
springboot 中事件监听模型的一种实现的更多相关文章
- SpringBoot Application事件监听
SpringBoot Application共支持6种事件监听,按顺序分别是: ApplicationStartingEvent:在Spring最开始启动的时候触发 ApplicationEnviro ...
- SpringBoot的事件监听
事件监听的流程分为三步:1.自定义事件,一般是继承ApplicationEvent抽象类.2.定义事件监听器,一般是实现ApplicationListener接口.3.a.启动的时候,需要将监听器加入 ...
- SpringBoot中如何监听两个不同源的RabbitMQ消息队列
spring-boot如何配置监听两个不同的RabbitMQ 由于前段时间在公司开发过程中碰到了一个问题,需要同时监听两个不同的rabbitMq,但是之前没有同时监听两个RabbitMq的情况,因此在 ...
- ASP.NET Core中配置监听URLs的五种方式
原文: 5 ways to set the URLs for an ASP.NET Core app 作者: Andrew Lock 译者: Lamond Lu 默认情况下,ASP. NET Core ...
- springboot~ EventListener事件监听的使用
EventListener事件触发和监听器可以对代码解耦,在一些与业务无关的,通用的操作方法,我们可以把它设计成事件监听器,像通知,消息这些模块都可以这样设计. 事件源 @Getter @Builde ...
- SpringBoot事件监听机制及观察者模式/发布订阅模式
目录 本篇要点 什么是观察者模式? 发布订阅模式是什么? Spring事件监听机制概述 SpringBoot事件监听 定义注册事件 注解方式 @EventListener定义监听器 实现Applica ...
- Spring之事件监听(观察者模型)
目录 Spring事件监听 一.事件监听案例 1.事件类 2.事件监听类 3.事件发布者 4.配置文件中注册 5.测试 二.Spring中事件监听分析 1. Spring中事件监听的结构 2. 核心角 ...
- SpringBoot事件监听机制源码分析(上) SpringBoot源码(九)
SpringBoot中文注释项目Github地址: https://github.com/yuanmabiji/spring-boot-2.1.0.RELEASE 本篇接 SpringApplicat ...
- jQuery中的事件监听小记
一,一个事件监听的简便写法 最近发现一个jQuery中事件监听的简洁写法,感觉方便好多.同时也深感自己基础薄弱,好多东西竟然都模棱两可.因此,记录的同时,也对jQuery事件监听做个小的总结 原文链接 ...
随机推荐
- 单页面登录——编码传参(oa会对#号会进行截断)
/** * querystring有四种方法:注意queryString与query-string不是同一个依赖包 * querystring.stringify 序列化; * querystri ...
- JMeter—断言(十一)
参考<全栈性能测试修炼宝典JMeter实战>第六章 JMeter 元件详解中第六节断言断言用来对服务器的响应数据做验证,常用的断言是响应断言,支持正则表达式. 一.BeanShell As ...
- 洗礼灵魂,修炼python(34)--面向对象编程(4)—继承
前面已经说到面向对象编程有封装,继承,多态三大特性,那么其中的继承则很重要,可以直接单独的拿出来解析 继承 1.什么是继承: 字面意是子女继承父母的家产或者特性等.而在编程里继承是指子类继承父类(基类 ...
- CSS网页菜单
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="WebUserContro ...
- 使用KeePass管理两步验证
目录 使用KeePass管理两步验证 两步验证 KeePass中管理两步验证 KeeTrayTOTP插件使用 使用KeePass管理两步验证 文:铁乐与猫 2018-9-9 KeePass 是一款管理 ...
- 个人博客作业Week3(微软必应词典客户端的案例分析)
软件缺陷常常又被叫做Bug,即为计算机软件或程序中存在的某种破坏正常运行能力的问题.错误,或者隐藏的功能缺陷.缺陷的存在会导致软件产品在某种程度上不能满足用户的需要.IEEE729-1983对缺陷有一 ...
- 最大子序和的golang实现
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 输入: [-,,-,,-,,,-,], 输出: 解释: 连续子数组 [,-,,] 的和最大,为 ...
- 新鲜出炉的jquery fileupload 插件
内容属原创,转载请注明出处 为什么做这个东东 项目中需要用到一个多附件上传的控件,找了一圈没找到中意的(唯一一个中意点的还不开源,费用比较高),这不,只得自己抡刀上了. 需求是什么 这么个上传的东东, ...
- 【学习笔记】python 进阶特性
__slots__魔法 在Python中,每个类都有实例属性.默认情况下Python用一个字典来保存一个对象的实例属性.这非常有用,因为它允许我们在运行时去设置任意的新属性. 然而,对于有着已知属性的 ...
- D - C Looooops POJ - 2115 欧几里德拓展
题意:就是看看for(; ;)多久停止. 最让我蛋疼的是1L和1LL的区别!让我足足wa了12发! 1L 是long类型的, 1LL为long long类型的! 思路: 这就是欧几里德扩展的标准式子了 ...