为了理解@EvenListener注解的底层原理,我们可以自己实现一个类似的注解模拟实现。

1.定义@MyListener注解

    @Target({ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)public @interface MyListener {}

2.注解使用

    @Componentstatic class SmsService {private static final Logger log = LoggerFactory.getLogger(SmsService.class);@MyListenerpublic void listener(MyEvent event) {log.debug("发送短信");}}

3.注解解析

public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestMyListener.class);SmsService smsService = context.getBean(SmsService.class);for(Method method : SmsService.class.getMethods()){if(method.isAnnotationPresent(MyListener.class)){ApplicationListener listener = new ApplicationListener<MyEvent>() {@Overridepublic void onApplicationEvent(MyEvent event) {try {method.invoke(smsService, event);}catch (Exception e){e.printStackTrace();}}};context.addApplicationListener(listener);}}context.getBean(MyService.class).doBusiness();context.close();}

 1)获取监听器类

 2)通过反射拿到方法

       判断方法上的注解是否是我们自定义的注解,如果是,创建ApplicationListener对象(这里使用了泛型去指定事件类型,如果不这样做可能会接收到别的事件而报错,比如说容器关闭事件),重写里面的监听事件的方法,通过反射调用加了@MyListener注解的方法。

 3)把监听器加入容器里面。

打印结果:

@MyListener注解实现了事件监听机制。

 4.改进点

       上面我们固定解析了监听类为SmsService类,现实情况是其它类上也可能加了@MyListener注解,我们可以做得更通用一些。

       (1)再写一个监听类EmailService。

    @Componentstatic class EmailService {private static final Logger log = LoggerFactory.getLogger(EmailService.class);@MyListenerpublic void listener(MyEvent event) {log.debug("发送邮件");}}

         2)遍历所有满足条件的bean

public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestMyListener.class);for (String beanName : context.getBeanDefinitionNames()){Object bean = context.getBean(beanName);for(Method method : bean.getClass().getMethods()){if(method.isAnnotationPresent(MyListener.class)){ApplicationListener listener = new ApplicationListener<MyEvent>() {@Overridepublic void onApplicationEvent(MyEvent event) {try {method.invoke(bean, event);}catch (Exception e){e.printStackTrace();}}};context.addApplicationListener(listener);}}}context.getBean(MyService.class).doBusiness();context.close();}

            3)测试结果

       容器监听了所有实现@MyListener注解的方法。

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Springboot + vue3实现的小区物业管理系统

项目描述本系统包含管理员和用户两个角色。管理员角色&#xff1a;用户管理&#xff1a;管理系统中所有用户的信息&#xff0c;包括添加、删除和修改用户。房屋信息管理&#xff1a;管理房屋信息&#xff0c;包括新增、查看、修改和删除房屋信息。车辆信息管理&#xff1a;管理…

交叉熵和KL散度

这个问题之前我也是傻傻分不清&#xff0c;决定整理一下&#xff0c;用更印象深刻的方式让人记住。核心联系&#xff1a;交叉熵 KL 散度 真实分布的熵 交叉熵作为 “绝对” 度量&#xff0c;会综合真实分布的熵&#xff08;固有难度&#xff09;与预测误差&#xff0c;直接体…

HTML 各种事件的使用说明书

HTML 各种事件的使用说明书 1. HTML 事件简介 HTML事件是浏览器或用户在网页上执行的动作或发生的事情。当这些事件发生时&#xff0c;可以通过JavaScript来响应和处理这些事件&#xff0c;从而实现网页的交互功能。事件处理是Web前端开发中实现动态交互的核心机制。 基本概…

Kafka面试精讲 Day 10:事务机制与幂等性保证

【Kafka面试精讲 Day 10】事务机制与幂等性保证 在分布式消息系统中&#xff0c;如何确保消息不丢失、不重复&#xff0c;是系统可靠性的核心挑战。Kafka自0.11版本起引入了幂等性Producer和事务性消息机制&#xff0c;彻底解决了“至少一次”语义下可能产生的重复消息问题&am…

时序数据库简介和安装

一、简介1. 什么是时序数据库&#xff1f;时序数据库是专门用于存储和处理时间序列数据的数据库系统。时间序列数据是指按时间顺序索引的一系列数据点。每个数据点都包含&#xff1a;一个时间戳&#xff1a;记录数据产生的时间。一个或多个指标值&#xff1a;例如温度、湿度、C…

comfyUI 暴露网络restful http接口

https://zhuanlan.zhihu.com/p/686893291 暴露websocket接口。 打开开发者选项 如图

linux系统address already in use问题解决

linux系统上某个端口被占用&#xff0c;如何解决&#xff1f;1.找到占用的进程编号&#xff1a;netstat -tulnp | grep :80002.强制杀死该进程kill -9 80603其他说明&#xff1a;1.查找占用端口的进程&#xff0c;可以用&#xff1a;lsof -i :8001 # 或者使用 netstat -tulnp |…

基于SpringBoot的家政保洁预约系统【计算机毕业设计选题 计算机毕业设计项目 计算机毕业论文题目推荐】

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

【Linux系统】 4. 权限(一)

一. shell 命令及运行原理基本理解1&#xff09;广义理解的操作系统包括&#xff1a;操作系统内核、外壳程序&#xff08;shell命令行、图形化界面&#xff09;、必要的软件。2&#xff09;狭义的操作系统&#xff1a;操作系统内核。3&#xff09;在用户和内核之间有一个外壳程…

6.python——字符串

python中用’ 和" "创建字符串 python的子字符串截取用[]取字符串拼接可以直接用相加。 python三引号允许一个字符串跨多行&#xff0c;其中无需进行转义&#xff08;所见即所得&#xff09;。 当你需要一块HTML或者SQL时&#xff0c;这时用字符串组合&#xff0c;特…

足球数据API接口的技术特性与应用价值分析

一、接口概述现代足球数据接口是基于RESTful架构的数据服务&#xff0c;通过标准化方式提供赛事相关信息。这类接口通常采用JSON格式传输数据&#xff0c;支持跨平台调用&#xff0c;为开发者提供结构化的足球赛事数据。二、数据覆盖范围主流足球数据接口通常包含以下数据类型&…

<android>反编译魔改安卓系统应用并替换

我们知道安卓系统基于稳定性、维护便利、性能优化等原因并未对原生系统apk进行混淆加密处理&#xff0c;由此就方便了我们反编译替换原生应用。 首先我们设备需要是root后的&#xff0c;我是使用的是小米5&#xff0c;刷的24.3版本的面具。首先我们需要取系统apk&#xff0c;这…

【Qt】项目的创建 and 各个控件的使用

一、项目的创建&#x1f50d;然后点击新建项目。&#x1f4d6;注意&#xff1a;路径不要带有中文&#xff0c;不然运行不了代码。&#x1f4d6;qmake是一个构建工具&#xff0c;在 Qt 写的程序&#xff0c;设计的到一系列的 "元编程" 技术&#xff0c;什么是元编程技…

大模型架构演进全景:从Transformer到下一代智能系统的技术路径(MoE、Mamba/SSM、混合架构)

当前大模型发展正经历着一个关键的技术分水岭。虽然Transformer架构自2017年问世以来主导了整个AI领域&#xff0c;但我们正见证着多种创新架构的涌现&#xff0c;每种都在试图解决Transformer的固有局限。本指南将系统性地解析当前主流架构的技术原理、适用场景与发展趋势&…

画世界笔刷合集(2000 + 款):含宫崎骏森系、鸭风人像、国潮等多风格 + 视频导入教程

预览&#xff1a; https://blog.csdn.net/2501_93092597/article/details/151330089?spm1011.2415.3001.5331 想在画世界创作却缺适配笔刷&#xff1f;手动绘制森系元素、人像细节耗时久&#xff0c;导入笔刷总失败&#xff0c;找配套背景 / 配色还得跨平台搜索&#xff1f;这…

03-Redis 安装指南:从版本选择到多系统部署(Windows+macOS+Linux)

目录引言一、安装 Redis 前必须明确的核心问题二、Redis 版本选择&#xff1a;稳定版 vs 开发版&#xff0c;该怎么选&#xff1f;2.1 版本规则&#xff1a;看 “次版本号” 辨稳定性2.2 稳定版与开发版核心差异2.3 版本选择建议三、多系统安装教程&#xff1a;step-by-step 实…

普通MYSQL数据库是怎么做sum操作的

MySQL 的 SUM()操作实现是一个结合​​执行引擎优化、存储结构利用和分组算法​​的高效过程。以下是其核心实现机制和优化策略&#xff1a;​​1. 执行流程概览​​以查询为例&#xff1a;SELECT department, SUM(salary) FROM employees GROUP BY department;​​执行步骤​​…

Claude-Flow AI协同开发:基础入门之 AI编排

1.1 引言&#xff1a;超越“代码生成器”的革命 在AI辅助开发的浪潮中&#xff0c;我们已经习惯了代码补全、函数生成等“代码生成器”工具。它们极大地提升了我们的编码效率&#xff0c;但通常仅限于解决孤立、单一的问题。当面对一个完整的项目或一个复杂的功能模块时&#x…

Linux中下载安装部署Redis7.4.5——并设置用户名、密码及其授权的保姆级教程

一、环境准备 环境准备 序号 说明 1 使⽤RHEL9或Almalinux9.1及其更高版本系统 #查看系统信息 cat /etc/os-release 2 Linux中需要Redis源码编译所需的gcc依赖 #1-检查是否已

健康度——设备健康续航条

在故障诊断与健康管理&#xff08;PHM&#xff09;领域和寿命预测领域中&#xff0c;健康度&#xff08;Health Index, HI&#xff09;是一个至关重要的概念&#xff0c;它旨在量化设备或系统的当前健康状态&#xff0c;并为预测其剩余使用寿命&#xff08;Remaining Useful Li…