后端视角看 EventBus:发布订阅总线的原理、场景与用法
大家好我是程序员天天困。今天聊一个能让你少写一大堆回调的东西——EventBus一个在 Android 和 Java 里都挺火的事件发布订阅库。我自己做后端多一些但这东西在 Android 用得最广所以咱们两边都照顾着讲争取你写哪端都能用得上。话不多说直接开始。一、EventBus 到底是干什么的EventBus 不是什么新发明它就是把「发布-订阅」模式做成一个开箱即用的总线让两个模块不用互相认识就能通信。EventBus发布订阅事件总线greenrobot 出品的开源库用发布-订阅模式解耦组件通信——发布者只管把事件丢进总线订阅者通过注解方法接收两者互不持有引用。你可以把它理解成「代码里的广播站」。广播站的比喻最贴切拿话筒的人喊一嗓子所有调到这个频道的接收器都能听到喊的人根本不用知道谁在听。回到后端你写 Spring 时用过的EventListener配ApplicationEventPublisher或者 Guava 的EventBus乃至 Kafka、RabbitMQ都是同一套发布订阅思想的不同重量级实现。EventBus 是其中最轻的一个一个约 60k 的 jar不依赖任何中间件在进程内同步或异步分发延迟在微秒级。它的运行机制简单到一句话发布者调post把事件丢进 EventBusEventBus 根据事件类型查到所有订阅了这个类型的方法依次调用。就这么直接发布者不关心谁来收订阅者也不关心谁发的。二、为什么需要它组件通信的痛那有人就会问了Android 自己不是有通信机制吗为啥还要再造一个 EventBus这得先看看原生的那套东西痛在哪。Android 想让组件之间传消息最常用的就两样Handler 和 BroadcastReceiver。Handler 用来切线程、投递消息BroadcastReceiver 用来发系统级广播。能用是能用但写起来烦——一堆样板代码不说发消息的还得知道收消息的是谁两边经常要互相持有引用组件一多引用关系就缠成一团。最常见的场景你在子线程里跑接口请求数据回来要刷新 UI得拿 Handler 切回主线程两个 Fragment 要互换数据得借 Activity 当中间人或者写个 Listener 接口回调。项目小的时候忍忍就过去了业务一膨胀这种回调套回调、引用套引用的写法代码量和耦合度一起失控。后端其实一个毛病——Service 之间互相Autowired最后织成一张谁也拆不动的网根子都是发布者把「我要通知谁」写死在了自己代码里。EventBus 的解法很简单A 不认识 B/C/D它只认识 EventBus。谁关心谁自己订阅发布者彻底从「通知谁」里解放出来新增一个订阅者发布者一行代码都不用改。下面这张图把两种方式摆在一起——左边是组件之间互相持有引用、回调层层传递右边是发布者只对总线 post订阅者各自从总线取谁也不认识谁。可能有人会问那我后端直接上 Kafka、RabbitMQ 不就完了为啥还要一个进程内的 EventBus两者解决的不是同一个量级的问题。MQ 是跨进程、跨机器的异步消息带持久化和集群EventBus 是单进程内的方法调用级通信没有网络、没有序列化开销延迟在微秒级。同一个 JVM 内部模块解耦上 MQ 是杀鸡用牛刀跨服务通信EventBus 又鞭长莫及。各管一段别混用。三、三步上手在 Spring Boot 里用 EventBusEventBus 的全部 API 浓缩成三步——定义事件、注册订阅、发送事件背下来就能用。它不绑 AndroidSpring Boot 后端一样能跑把依赖换成eventbus-java就行。如果你团队已经定了用 EventBus或者要和 Android 端共用一套事件模型下面这套 Spring Boot 写法直接抄至于要不要在 Spring 里上它选型建议放在第六节。第一步引入 Maven 依赖。在pom.xml里加这一段!-- 以 Maven Central 3.3.1 为准Spring Boot 2.x 注解用 javax3.x 用 jakarta --dependencygroupIdorg.greenrobot/groupIdartifactIdeventbus-java/artifactIdversion3.3.1/version/dependency第二步定义事件 写订阅者。事件就是一个普通 POJO不继承任何基类订阅者用Subscribe标注接收方法方法必须 public、有且仅有一个参数publicclassLoginEvent{privatefinalStringusername;publicLoginEvent(Stringusername){this.usernameusername;}publicStringgetUsername(){returnusername;}}ComponentpublicclassUserModule{Subscribe(threadModeThreadMode.POSTING)publicvoidonLogin(LoginEventevent){System.out.println(用户 event.getUsername() 已登录);}PostConstruct// Bean 启动时注册publicvoidinit(){EventBus.getDefault().register(this);}PreDestroy// Bean 销毁时注销publicvoiddestroy(){EventBus.getDefault().unregister(this);}}把订阅者声明成 Spring 的Component再用PostConstruct注册、PreDestroy注销register 和 unregister 就跟着 Bean 生命周期自动成对不用你手动记着去调。第三步发送事件。在任何 Service 里直接 post发布者完全不需要知道谁在监听ServicepublicclassLoginService{publicvoidlogin(Stringusername){// 业务处理……EventBus.getDefault().post(newLoginEvent(username));}}我见过太多线上 OOM根因就是register了却没unregister——EventBus 持有订阅者引用对象回收不掉。所以哪怕图省事也务必让注册和注销跟着生命周期走别只 register 不注销。下面这张时序图展示了从post到被订阅方法处理的完整链路发布者 post 后EventBus 按事件类型查订阅表再按线程模式决定同步直调还是丢进线程池。四、Subscribe 三个关键参数线程模式、粘性事件、优先级Subscribe注解的三个参数不是花架子它们决定了事件在哪个线程跑、能不能收到「早到」的事件、谁先收到。SubscribeEventBus 的订阅方法注解标注「这个方法要接收什么类型的事件」可指定线程模式、是否粘性、优先级。被注解的方法要求 public 修饰、有且仅有一个参数。粘性事件Sticky EventpostSticky发出后会被 EventBus 缓存下来的事件之后新注册的订阅者也能收到它。你可以理解成「迟到的订阅者也能拿到上一条广播」。线程模式ThreadMode决定了订阅方法在哪个线程被执行。纯 Java 后端主要用 POSTING 和 ASYNCMAIN 系列依赖 Android 主线程后端用不到ThreadMode在哪执行纯 Java 能用典型场景POSTINGpost 所在线程直接同步调用能不耗时的事件最常用ASYNC永远丢进线程池异步执行能订阅者要做耗时 IOBACKGROUNDpost 在主线程则入池在子线程则直接调能轻量后台任务MAINAndroid 主线程执行否更新 UIMAIN_ORDERED主线程按顺序非阻塞否多个 UI 更新串行粘性事件有个坑要单独说缓存的粘性事件不会自动消失重复postSticky同类型会覆盖旧的但如果你忘了removeStickyEvent换场景后新订阅者可能收到一条本不该收的「历史事件」。我的习惯是粘性事件用完立刻removeStickyEvent别让缓存兜着脏数据。优先级priority是个 int数字越大越先收到且只在同一线程模式下才有意义。五、什么场景下用 EventBusEventBus 适合「一对多、发布者不想知道订阅者是谁」的场景不适合「调用方需要返回值」或「强顺序依赖」的场景。后者本质上是在做方法调用硬套事件总线只会让链路更难追踪。几类典型场景全局状态广播登录登出、网络断连恢复——一处 post多处 UI 或模块各自响应。跨层组件通信Fragment 之间、Fragment 与 Activity、Service 与页面不再借 Activity 中转。后端模块解耦领域事件的轻量版——下单成功后通知积分、库存、推送模块各自处理下单服务不关心下游有谁。配置热更新配置中心拉到新值后 post 一个ConfigChangedEvent各模块自己刷新。可能有人会问后端真要用 EventBus 吗还是直接 SpringEventListener更香老实说纯 Spring 后端我更推荐用 Spring 自带的EventListener零额外依赖、和容器生命周期天然集成、还支持TransactionalEventListener跟着事务走。EventBus 的甜区在 Android 和非 Spring 的纯 Java 工程——没有 Spring 容器、又想要个轻量发布订阅它比手撸观察者模式省心。要是跨进程老老实实上 MQ。六、后端视角的取舍EventBus vs Guava vs Spring选哪个看你在不在 Spring 容器里、要不要跨进程、对依赖体积多敏感。方案依赖线程模型跨进程适合谁greenrobot EventBus~60k jarThreadMode 五种否Android / 非 Spring 纯 JavaSpring 里也能跑Guava EventBusGuava 整包同步或异步二选一否已用 Guava 的纯 Java 项目Spring EventListenerSpring 容器同步可配异步否任何 Spring 后端Kafka / RabbitMQ独立中间件异步是跨服务、跨进程EventBus 也不是银弹几个老问题一直都在事件类会越定义越多一个项目几十个 Event 类很常见订阅方法靠反射查找编译时索引能优化但要配 annotation processor忘了unregister就内存泄漏最麻烦的是事件流难追踪——post一条事件到底谁会响应、什么顺序得全局搜调试链路偏长。这些都是它换来解耦的代价。写法上以 Maven Central 的org.greenrobot:eventbus:3.3.12021 年最后大版本为准长期稳定。Android 新项目也有人用 Kotlin 的 Flow / Channel 替代但就「最快上手、几行解耦」而言EventBus 依然是门槛最低的方案之一。后端要不要上 EventBus我的判断就一句在 Spring 里别折腾EventListener已经够用写 Android 或纯 Java 又想轻量解耦EventBus 依然是几行代码搞定、最省心的那个。跨进程的事交给 MQ别让一条进程内总线去干它不该干的活。

相关新闻

role仓库之Galaxy

role仓库之Galaxy

Ansible Galaxy 是官方统一角色仓库平台:https://galaxy.ansible.com 类似于GitHub,我们可以在这个平台上搜索别人写好的roles,然后下载到本地使用。 核心命令: 在线搜索 nginx 相关角色 ansible-galaxy search nginx 查看角色详情…

2026/7/19 23:50:31 阅读更多 →
OCR C++ Tesseract监控识别进度(多线程)

OCR C++ Tesseract监控识别进度(多线程)

这个程序使用C标准多线程库监控Tesseract OCR的识别进度。输入图片&#xff1a;程序运行后会在CMD里打印识别结果&#xff1a;第一行打印识别进度&#xff0c;在up的电脑上只从1%加载到61%,就开始打印输出结果了。代码&#xff1a;#include <tesseract/baseapi.h> #inclu…

2026/7/19 23:50:31 阅读更多 →
OCR C++ Tesseract检测图像的倾斜角度

OCR C++ Tesseract检测图像的倾斜角度

这个程序使用Tesseract OCR检测图像的页面布局信息&#xff0c;包含图像的倾斜角度等信息。输入图片稍微有一点点倾斜&#xff1a;运行程序之后会在CMD里输出检测结果&#xff1a;方向0表示图片没有旋转。书写方向0表示从左到右。文本行顺序2表示文本的阅读顺序是从上到下、从左…

2026/7/19 23:50:31 阅读更多 →

最新新闻

国内封装齐全的BGA芯片测试座HMILU品牌接触稳定性远超同行业标准

国内封装齐全的BGA芯片测试座HMILU品牌接触稳定性远超同行业标准

在芯片测试领域&#xff0c;芯片测试座的性能表现至关重要&#xff0c;其中接触稳定性是衡量其质量的核心指标之一。今天我们就来深入探讨一下国内深圳市鸿怡电子有限公司旗下的HMILU品牌BGA芯片测试座&#xff0c;它凭借封装齐全和卓越的接触稳定性在市场中脱颖而出。一、市场…

2026/7/20 15:13:46 阅读更多 →
市场知名的GPU芯片测试治具销售厂家销量远超第二名

市场知名的GPU芯片测试治具销售厂家销量远超第二名

在当前的半导体行业中&#xff0c;芯片测试治具作为关键设备之一&#xff0c;其成本控制对于企业的整体运营至关重要。本文将通过具体数据和案例&#xff0c;探讨如何有效控制CPU芯片测试座的成本&#xff0c;并提供实操建议。一、市场现状与痛点根据行业数据显示&#xff0c;目…

2026/7/20 15:13:46 阅读更多 →
3步打造终极无广告看番体验:oneAnime开源客户端完整指南

3步打造终极无广告看番体验:oneAnime开源客户端完整指南

3步打造终极无广告看番体验&#xff1a;oneAnime开源客户端完整指南 【免费下载链接】oneAnime 一款简洁清爽无广告的看番软件。 一款带弹幕的 anime1 第三方客户端&#xff0c;界面符合 Material You 规范。 项目地址: https://gitcode.com/gh_mirrors/on/oneAnime one…

2026/7/20 15:13:46 阅读更多 →
ApolloScanner核心功能解析:从资产识别到漏洞检测

ApolloScanner核心功能解析:从资产识别到漏洞检测

ApolloScanner核心功能解析&#xff1a;从资产识别到漏洞检测 【免费下载链接】ApolloScanner 自动化巡航扫描框架&#xff08;可用于红队打点评估&#xff09; 项目地址: https://gitcode.com/gh_mirrors/ap/ApolloScanner ApolloScanner是一款强大的自动化巡航扫描框架…

2026/7/20 15:13:46 阅读更多 →
AI社交发布系统崩溃复盘(2024真实故障录屏级解析):从Token泄漏到平台封禁的全链路溯源

AI社交发布系统崩溃复盘(2024真实故障录屏级解析):从Token泄漏到平台封禁的全链路溯源

更多请点击&#xff1a; https://kaifayun.com 第一章&#xff1a;AI社交发布系统崩溃复盘&#xff08;2024真实故障录屏级解析&#xff09;&#xff1a;从Token泄漏到平台封禁的全链路溯源 故障时间线与关键节点 2024年3月17日14:22&#xff08;UTC8&#xff09;&#xff0c…

2026/7/20 15:13:46 阅读更多 →
计算机毕业设计之django基于 Python 的仓库管理系统设计与实现

计算机毕业设计之django基于 Python 的仓库管理系统设计与实现

信息技术是当今社会发展的重要方向之一&#xff0c;它已经深入到各个行业中。随着计算机技术的发展&#xff0c;信息技术已经从传统的数据处理转变为网络信息的处理和交互。在管理方面&#xff0c;通过信息管理技术&#xff0c;系统可以快速的处理大量的数据&#xff0c;并且能…

2026/7/20 15:12:45 阅读更多 →

日新闻

2026 WAIC:努比亚二代“豆包手机”NaviX Ultra亮相,智能体验全面升级!

2026 WAIC:努比亚二代“豆包手机”NaviX Ultra亮相,智能体验全面升级!

7月18日智东西消息&#xff0c;在2026 WAIC期间&#xff0c;努比亚联合字节豆包打造的二代“豆包手机”努比亚NaviX Ultra首次亮相&#xff0c;相比一代有诸多升级。智能体手机理念中兴通讯终端事业部总裁、努比亚总裁倪飞表示&#xff0c;智能体手机要从人操作手机变为手机帮人…

2026/7/20 0:00:34 阅读更多 →
努比亚NaviX Ultra亮相WAIC,智能体手机能否让用户生活更简单?

努比亚NaviX Ultra亮相WAIC,智能体手机能否让用户生活更简单?

努比亚NaviX Ultra&#xff1a;外观与功能双升级在2026 WAIC期间&#xff0c;首次亮相的努比亚NaviX Ultra吸引了众多目光。它是努比亚联合字节豆包打造的二代“豆包手机”&#xff0c;与一代努比亚M153相比&#xff0c;外观设计变化较大。其机身背部搭载横向排布的大尺寸影像模…

2026/7/20 0:00:34 阅读更多 →
C# 将逗号分割的字符串转换为long,并添加到List<long>

C# 将逗号分割的字符串转换为long,并添加到List<long>

目录 方法1&#xff1a;使用Split和Convert.ToInt64 方法2&#xff1a;使用LINQ的Select和ToList 方法3&#xff1a;使用TryParse进行异常安全转换&#xff08;推荐&#xff09; 如果您喜欢此文章&#xff0c;请收藏、点赞、评论&#xff0c;谢谢&#xff0c;祝您快乐每一天…

2026/7/20 0:00:34 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中&#xff0c;我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源&#xff0c;还是配置文件、证书等&#xff0c;都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下&#xff0c;但这…

2026/7/20 5:57:49 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP&#xff08;轻量级目录访问协议&#xff09;作为企业级身份认证的黄金标准&#xff0c;已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时&#xff0c;发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/20 4:31:26 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”&#xff0c;而是以可解释、可审计、可迭代的方式&#xff0c;赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/20 5:56:42 阅读更多 →

月新闻