前言: 事件监听模型是一种常用的设计模式,在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 中事件监听模型的一种实现的更多相关文章

  1. SpringBoot Application事件监听

    SpringBoot Application共支持6种事件监听,按顺序分别是: ApplicationStartingEvent:在Spring最开始启动的时候触发 ApplicationEnviro ...

  2. SpringBoot的事件监听

    事件监听的流程分为三步:1.自定义事件,一般是继承ApplicationEvent抽象类.2.定义事件监听器,一般是实现ApplicationListener接口.3.a.启动的时候,需要将监听器加入 ...

  3. SpringBoot中如何监听两个不同源的RabbitMQ消息队列

    spring-boot如何配置监听两个不同的RabbitMQ 由于前段时间在公司开发过程中碰到了一个问题,需要同时监听两个不同的rabbitMq,但是之前没有同时监听两个RabbitMq的情况,因此在 ...

  4. ASP.NET Core中配置监听URLs的五种方式

    原文: 5 ways to set the URLs for an ASP.NET Core app 作者: Andrew Lock 译者: Lamond Lu 默认情况下,ASP. NET Core ...

  5. springboot~ EventListener事件监听的使用

    EventListener事件触发和监听器可以对代码解耦,在一些与业务无关的,通用的操作方法,我们可以把它设计成事件监听器,像通知,消息这些模块都可以这样设计. 事件源 @Getter @Builde ...

  6. SpringBoot事件监听机制及观察者模式/发布订阅模式

    目录 本篇要点 什么是观察者模式? 发布订阅模式是什么? Spring事件监听机制概述 SpringBoot事件监听 定义注册事件 注解方式 @EventListener定义监听器 实现Applica ...

  7. Spring之事件监听(观察者模型)

    目录 Spring事件监听 一.事件监听案例 1.事件类 2.事件监听类 3.事件发布者 4.配置文件中注册 5.测试 二.Spring中事件监听分析 1. Spring中事件监听的结构 2. 核心角 ...

  8. SpringBoot事件监听机制源码分析(上) SpringBoot源码(九)

    SpringBoot中文注释项目Github地址: https://github.com/yuanmabiji/spring-boot-2.1.0.RELEASE 本篇接 SpringApplicat ...

  9. jQuery中的事件监听小记

    一,一个事件监听的简便写法 最近发现一个jQuery中事件监听的简洁写法,感觉方便好多.同时也深感自己基础薄弱,好多东西竟然都模棱两可.因此,记录的同时,也对jQuery事件监听做个小的总结 原文链接 ...

随机推荐

  1. C#语言————第二章 C#语言快速热身

    第二章    C#语言快速热身 ***********一.选择结构**************** 1:if选择结构与java的if选择结构语法完全相同 2:switch选择结构 ①:常量表达式的值可 ...

  2. OpenCV 的颜色空间转换

    # coding: utf-8 ''' 第13章主要介绍:颜色空间转换 ''' import cv2 import numpy as np ''' 经常用到的颜色空间转换是: BGR<-> ...

  3. [HDFS_add_1] HDFS 启动过程分析

    0. 说明 HDFS 文件概念 && HDFS 启动过程分析 1. HDFS 文件概念 [1.1 NameNode 职能] 存储文件类型.大小.权限.路径等等元数据 通过 edits( ...

  4. JDK动态代理源码解析

    动态代理.静态代理优缺点     关于JDK的动态代理,最为人熟知的可能要数Spring AOP的实现,默认情况下,Spring AOP的实现对于接口来说就是使用的JDK的动态代理来实现的,而对于类的 ...

  5. linux命令总结之tr命令

    什么是tr命令?tr,translate的简写,translate的翻译: [trænsˈleit] vi. 翻译, 能被译出 vt. 翻译, 解释, 转化, 转变为, 调动 在这里用到的意思是转化, ...

  6. Python中的 redis keyspace 通知

    介绍 Redis是内存中的数据结构存储,用于缓存.高速数据摄取.处理消息队列.分布式锁定等等. 与其他内存存储相比,使用Redis的优势在于它提供了持久性和数据结构,比如列表.集合.排序集合和散列. ...

  7. openssl windows 生成公钥与私钥

    链接: https://pan.baidu.com/s/1qn-qeFxovor-vcAWFl8jIw 提取码: zy5v 一,下载安装windows平台openssl密钥生成工具,执行安装目录bin ...

  8. YOLO2(1)配置安装win10+openvc2413+VS2013 简单测试官例

    参考官网 https://github.com/AlexeyAB/darknet#how-to-compile-on-windows https://github.com/AlexeyAB/darkn ...

  9. Java基础之多线程篇(线程创建与终止、互斥、通信、本地变量)

    线程创建与终止 线程创建 Thread类与Runnable接口的关系 public interface Runnable { public abstract void run(); } public ...

  10. numpy的shape 和 gt的x、y坐标之间容易引起误会

    用numpy来看shape,比如np.shape(img_data),会得到这样的结果(600,790,3) 注意:600不是横坐标,而是表示多少列,790才是横坐标 用numpy测试就可以看出: & ...