一起学SF框架系列4.8-模块context-事件机制(Event)

news2024/11/17 12:21:55

ApplicationContext中的事件处理是通过ApplicationEvent类和ApplicationListener接口提供的。如果将实现ApplicationListener接口的bean部署到上下文中,则每次将ApplicationEvent发布到ApplicationContext时,都会通知该bean。从本质上讲,这是标准的观察者设计模式。从Spring 4.2开始,提供了一个基于注释的事件模型,以及发布任何任意事件(即不一定从ApplicationEvent扩展的对象)的能力。

事件机制

Spring的事件机制是为同一应用程序容器中Spring bean之间的简单通信而设计的。机制工作示意图:
在这里插入图片描述
工作过程如下:
1、定义事件
2、事件发布bean通过发布器发布消息(默认发布器是)ApplicationContext。
3、发布器调用广播机广播方法。
4、广播机选择匹配消息的事件接收Bean,调用onApplication处理消息。
事件接收Bean在初始化过程中自动注册到广播机。

事件发布

发布实现

发布事件的bean通过调用ApplicationEventPublisher.publishEvent(Object event)发布事件,该方法实现在AbstractApplicationContext中,代码如下:

	protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
		Assert.notNull(event, "Event must not be null");

		// Decorate event as an ApplicationEvent if necessary
		ApplicationEvent applicationEvent;
		if (event instanceof ApplicationEvent applEvent) {
			applicationEvent = applEvent;
		}
		else {
			//创建为一个PayloadApplicationEvent
			applicationEvent = new PayloadApplicationEvent<>(this, event, eventType);
			if (eventType == null) {
				eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
			}
		}

		// Multicast right now if possible - or lazily once the multicaster is initialized
		if (this.earlyApplicationEvents != null) {
			//延迟官博
			this.earlyApplicationEvents.add(applicationEvent);
		}
		else {
			//立即广播 注1
			getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
		}

		//如果存在父容器,在父容器中广播
		// Publish event via parent context as well...
		if (this.parent != null) {
			if (this.parent instanceof AbstractApplicationContext abstractApplicationContext) {
				abstractApplicationContext.publishEvent(event, eventType);
			}
			else {
				this.parent.publishEvent(event);
			}
		}
	}

注1:事件广播器实际就是对所有Listener进行注册管理,在广播时逐一按事件匹配广播。事件广播器如果由应用实现,需实现ApplicationEventMulticaster接口;如果应用没有实现,则用spring提供的SimpleApplicationEventMulticaster作为事件广播器。

框架事件

ContextRefreshedEvent:ApplicationContext 初始化或刷新时发布。对应实现AbstractApplicationContext.finishRefresh()
ContextStartedEvent:ApplicationContext 调用start()方法时发布。对应实现AbstractApplicationContext.start()
ContextStoppedEvent:ApplicationContext 调用stop()方法时发布。对应实现AbstractApplicationContext.stop()
ContextClosedEvent:ApplicationContext 调用close()方法时发布,或者JVM关闭时发布。对应实现AbstractApplicationContext.doClose()
RequestHandledEvent:在WebApplicationContext中,当一个request完成时发布。
ServletRequestHandledEvent:RequestHandledEvent 子类,在ServletContext下使用。

自定义事件

定义事件

自定义事件继承ApplicationEvent 。

public class BlockedEmailEvent extends ApplicationEvent {
	//事件类的属性可以当做事件传参
	private final String email;
	private final String content;

	public BlockedEmailEvent(Object source, String email, String content) {
		//ApplicationEvent构建
		super(source);
		this.email= email;
		this.content = content;
	}
}

事件发布

若要发布自定义ApplicationEvent,在ApplicationEventPublisher上调用publishEvent()方法。通常,这是通过创建一个实现ApplicationEventPublisherware的类并将其注册为Springbean来完成的。下面实例就是发送email时,如果是黑名单,则不发送并发送BlockedEmailEvent

@Component
public class EmailService implements ApplicationEventPublisherAware {
	//阻止发送名单
	private List<String> blockedList;
	//发布器
	private ApplicationEventPublisher publisher;

	public void setBlockedList(List<String> blockedList) {
		this.blockedList = blockedList;
	}

	//使用容器的事件发布器(容器会自动调用该方法)
	public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
		this.publisher = publisher;
	}

	public void sendEmail(String email, String content) {
		//通知没有发送的email
		if (blockedList.contains(email)) {
			publisher.publishEvent(new BlockedEmailEvent(this, email, content));
			return;
		}
		// 真正发送email...
	}
}

事件接收

事件接收分为同步接收和异步接收。

同步接收

ApplicationListener同步接收事件,表示发送者的publishEvent()方法会阻塞,直到所有侦听器都完成了对事件的处理。同步一个优点是,当侦听器接收到事件时,如果事务上下文可用,它将在发布者的事务上下文中操作。

代码方式

public class BlockedEmailListener implements ApplicationListener<BlockedEmailEvent> {
	public void onApplicationEvent(BlockedEmailEvent event) {
		//接收到对应事件,进行处理
		// notify appropriate parties via notificationAddress...
	}
}

注解方式

public class BlockedEmailListener {
	//注解,参数为事件
	@EventListener
	public void processBlockedEmailEvent(BlockedEmailEvent event) {
		// notify appropriate parties via notificationAddress...
	}
}

异步接收

public class BlockedEmailListener {
	//注解,参数为事件
	@EventListener
	@Async
	public void processBlockedEmailEvent(BlockedEmailEvent event) {
		// notify appropriate parties via notificationAddress...
	}
}

处理顺序

如果一个事件有多个Listener,且有先后顺序要求,用注解@Order,通常同@EventListener配套使用。

public class BlockedEmailListener {
	//注解,参数为事件
	@EventListener
	@Order(5)
	public void processBlockedEmailEvent(BlockedEmailEvent event) {
		// notify appropriate parties via notificationAddress...
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/692451.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Allegro如何使用打印预览功能操作指导

Allegro如何使用打印预览功能操作指导 Allegro时常需要使用打印功能,将某个视图打印成pdf文件,如下图 在打印成pdf文件之前,可以使用打印预览的功能,具体操作如下 点击shape Add Rect命令Options出现如下选项<

阿里云地域和可用区分布表

阿里云服务器地域和可用区有哪些&#xff1f;阿里云服务器地域节点遍布全球29个地域、88个可用区&#xff0c;包括中国大陆、中国香港、日本、美国、新加坡、孟买、泰国、首尔、迪拜等地域&#xff0c;同一个地域下有多个可用区可以选择&#xff0c;阿里云服务器网分享2023新版…

Nginx的Location和Rewrite

目录 Rewrite简介 1.0 Rewrite实际场景 1.1 Rewrite跳转场景 1.2 Rewrite跳转实现 1.3 Nginx正则表达式 1.4 Rewrite命令&&语法格式 1.5 flag标记说明 2 Location分类 2.1 Location优先级 3 Rewrite&&Location比较 4 场景跳转实验 4.1 基于域名的跳转 …

vcruntime140.dll无法继续执行代码怎么办

今天打开photoshop软件的时候&#xff0c;突然间就打不开&#xff0c;电脑报错由于找不到vcruntime140.dll&#xff0c;无法继续执行此代码&#xff0c;然后我就把photoshop卸载了&#xff0c;再重新安装&#xff0c;依然还是报错。这个可怎么办&#xff1f;vcruntime140.dll如…

【笔记】肥胖代码:减肥的秘密

直接原因与根本原因 直接原因与根本原因的区别是什么&#xff1f;直接原因是直接造成体重增加的原因&#xff0c;根本原因是导致事物发生变化的根源。 以酗酒为例。酗酒的原因是什么&#xff1f; 直接原因是饮酒过量。这是不可否认的事&#xff0c;但显然不能解决问题。直接…

佑友防火墙默认口令及RCE漏洞

先用fofa脚本爬取所有碧海威相关资产&#xff08;fofa脚本下载地址&#xff1a;&#xff09; python3 fofa-cwillchris.py -k title"佑友防火墙" 将上面爬取到的文件&#xff08;一般是final****.txt&#xff09;移动到脚本目录下&#xff0c;保存为1.txt ./佑友防…

浅谈智能安全用电系统在轨道交通中的应用

安科瑞 华楠 摘要&#xff1a; 随着轨道交通电气设备的增加和用电负荷的变大&#xff0c;用电安全问题愈发突出&#xff0c;而对电力状况在线监测和故障预警是实现安全用电的关键。本文研究了轨道交通安全用电智能监测系统。该系统通过电力载波技术可利用原电缆进行数据传输&am…

适用ddddocr自动化测试验证码识别

原打算使用tesseract进行验证码识别的但后面发现实在太辣鸡了 不知道tesseract以及没安装的可以看这篇文章&#xff1a; tesseract安装以及联调python 使用tesseract的代码&#xff1a; import pytesseract from PIL import Image, ImageEnhance """ 步骤①&…

DOTA大环配体化合物:DOTA PEG5 amine/azide/DBCO,特点分享说明

一、DOTA-PEG5-amine&#xff0c;DOTA PEG5 NH2&#xff0c;DOTA-PEG5-amine HCl salt&#xff0c;DOTA五聚乙二醇氨基Product structure&#xff1a; 1.CAS No&#xff1a;N/A 2.Molecular formula&#xff1a;C28H54N6O12 3.Molecular weight&#xff1a;666.8 5.Appearance …

【图像处理】去雾代码收(附halcon、python、C#、VB、matlab)

【图像处理】去雾代码收&#xff08;附halcon、python、C#、VB、matlab&#xff09; 一、halcon算法1.1 halcon算法源码1.2 halcon算法效果图![在这里插入图片描述](https://img-blog.csdnimg.cn/8ad5217a59be4de29b5a7b6eee997b85.png#pic_center) 二、opencv算法2.1 python源…

了解架构是什么

前言&#xff1a; \textcolor{Green}{前言&#xff1a;} 前言&#xff1a; &#x1f49e;这个专栏就专门来记录一下寒假参加的第五期字节跳动训练营 &#x1f49e;从这个专栏里面可以迅速获得Go的知识 了解架构是什么 01. 什么是架构1.1 定义1.1 问题1.2 什么是架构 - 单机1.3 …

Linux服务器同步Windows目录同步-rsync

前言 最近需要&#xff0c;Linux的服务器同步Windows的一个目录。查了下&#xff0c;大概有三种方法&#xff1a;网盘同步&#xff1b;rsync同步&#xff1b;挂载目录。 网盘同步&#xff0c;可以选择搭建一个Nextcloud 。但是问题在于&#xff0c;我需要的是&#xff0c;客户…

react context上下文与vue中 provide inject的用法区别

一、react中&#xff1a; 数据传递 1、引入createContext import { createContext } from "react"; 2、创建并导出 export const FspThemeContext createContext({}); 3、传递数据&#xff08;value项不能缺少&#xff01;&#xff01;&#xff09; ①不解构…

微流控芯片压力和流量的超高精度串级控制解决方案

摘要&#xff1a;针对微流控芯片压力驱动进样系统中压力和流量的高精度控制&#xff0c;本文提出了国产化替代解决方案。解决方案采用了积木式结构&#xff0c;便于快速搭建起气压驱动进样系统。解决方案的核心是采用了串级控制模式&#xff0c;结合高精度的传感器、电气比例阀…

JMeter如何进行多服务器远程测试

JMeter是Apache软件基金会的开源项目&#xff0c;主要来做功能和性能测试&#xff0c;用Java编写。 我们一般都会用JMeter在本地进行测试&#xff0c;但是受到单个电脑的性能影响&#xff0c;往往达不到性能测试的要求&#xff0c;无法有效的模拟高并发的场景&#xff0c;那么…

云计算服务模式、PaaS、SaaS都是啥?

什么是云计算服务模式 云计算服务模式是指云服务提供商提供的不同类型的云计算服务&#xff0c;包括基础设施即服务&#xff08;IaaS&#xff09;、平台即服务&#xff08;PaaS&#xff09;和软件即服务&#xff08;SaaS&#xff09;等。这些服务可以帮助企业在云端进行资源共…

Mysql找出执行慢的SQL【慢查询日志使用与分析】

分析慢SQL的步骤 慢查询的开启并捕获&#xff1a;开启慢查询日志&#xff0c;设置阈值&#xff0c;比如超过5秒钟的就是慢SQL&#xff0c;至少跑1天&#xff0c;看看生产的慢SQL情况&#xff0c;并将它抓取出来explain 慢SQL分析show Profile。&#xff08;比explain还要详细…

WideResNet(宽残差网络)算法解析-鸟类识别分类-Paddle实战

文章目录 一、理论基础1.前言2.设计理念2.1 ResNet算法2.1.1 residual&#xff08;残差结构&#xff09;模块2.1.2 residual的计算方式2.1.3 ResNet中两种不同的residual2.1.4 Batch Normalization&#xff08;批归一化&#xff09; 2.2 WideResNet(WRNs)算法2.2.1 宽残差块2.2…

vue2项目引入vant组件库

Vant官网 Vant 2 - Mobile UI Components built on Vue

【零基础入门学习Python---Python数据处理和存储保姆级教程】

&#x1f680; Python &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…