java中实现发布-订阅模式的核心是通过事件总线或主题接口解耦发布者与订阅者,支持泛型类型安全、spring事件集成及线程安全调度,强调职责分离与开闭原则。

在 Java 面向对象架构中实现发布-订阅模式,核心是解耦发布者(Publisher)与订阅者(Subscriber),通过一个中间媒介(通常是事件总线或主题对象)来管理消息的分发。不依赖具体实现类,而是基于接口或抽象类型协作,符合开闭原则和依赖倒置原则。
定义事件与主题接口
先设计可扩展的事件模型和主题契约,避免硬编码具体业务类型:
- 定义通用 Event 接口或基类(如
public interface Event { String getType(); }),便于后续扩展不同事件类型 - 声明 Topic(或 Subject)接口,含
register(Subscriber)、unregister(Subscriber)、publish(Event)方法 - 定义 Subscriber 函数式接口(如
@FunctionalInterface public interface Subscriber { void onEvent(Event event); }),支持 Lambda 订阅
实现内存内事件总线(轻量级中心化调度)
用线程安全的集合管理订阅关系,确保多线程环境下注册/通知安全:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 使用
CopyOnWriteArrayList<subscriber></subscriber>存储订阅者,避免遍历时并发修改异常 -
publish()方法遍历所有订阅者并异步或同步调用其onEvent()—— 同步适合简单场景;如需解耦执行,可配合ExecutorService异步投递 - 支持按事件类型过滤:在
publish(Event e)中检查e.getType(),只通知对该类型感兴趣的订阅者(可结合 Map> 实现分类存储)
利用观察者模式增强类型安全(Java 8+ 推荐)
借助泛型让事件传递具备编译期类型检查,减少运行时转型错误:
- 定义泛型主题
interface Topic<t extends event> { void subscribe(Consumer<t> handler); void publish(T event); }</t></t> - 实现类如
SimpleTopic<usercreatedevent></usercreatedevent>只接受UserCreatedEvent类型事件,订阅时传入user -> sendWelcomeEmail(user),IDE 可自动推导参数类型 - 避免传统 Observer/Observable 中的
Object参数和强制类型转换
集成 Spring 的事件机制(企业级推荐方案)
若项目已用 Spring,直接复用其事件基础设施,更易测试、支持事务绑定与异步:
- 自定义事件继承
ApplicationEvent(如class OrderPaidEvent extends ApplicationEvent) - 监听器用
@EventListener注解方法,Spring 自动注册到ApplicationEventMulticaster - 需要异步时加
@Async,需事务后触发时用@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) - 完全基于接口编程,无需手动维护订阅列表,容器统一管理生命周期
不复杂但容易忽略的是事件传播边界——避免在事件处理中再发布新事件导致无限递归,建议限制嵌套层级或使用标记位控制。关键不在代码行数,而在职责划分是否清晰:发布者不关心谁接收,订阅者不感知谁发出,中间件只管路由与调度。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










