java事件总线用consumer抽象监听器、concurrenthashmap+copyonwritearraylist管理订阅、泛型支持类型隔离,事件建议为不可变pojo;进阶支持isassignablefrom实现父子类通配监听。

Java 高级实战中,用函数式接口实现轻量级发布-订阅事件总线,核心在于:用 java.util.function 中的函数式接口(如 Consumer<t></t>)抽象监听器,配合线程安全的容器(如 CopyOnWriteArrayList)管理订阅者,再通过泛型支持事件类型隔离。
定义事件基类与泛型事件总线
不强制继承,但建议事件为不可变 POJO,便于类型推导和线程安全:
public class UserLoginEvent {
private final String userId;
public UserLoginEvent(String userId) { this.userId = userId; }
public String getUserId() { return userId; }
}
事件总线使用泛型 + 函数式接口作为监听器契约:
public class EventBus {
private final Map<class>, List<consumer>>> listeners
= new ConcurrentHashMap();
public <t> void subscribe(Class<t> eventType, Consumer<t> handler) {
listeners.computeIfAbsent(eventType, k -> new CopyOnWriteArrayList())
.add(handler);
}
@SuppressWarnings("unchecked")
public <t> void publish(T event) {
List<consumer>> handlers = listeners.get(event.getClass());
if (handlers != null) {
handlers.forEach(h -> ((Consumer<t>) h).accept(event));
}
}
}
</t></consumer></t></t></t></t></consumer></class>
利用函数式接口简化监听注册
得益于 Consumer 是函数式接口,可直接用方法引用、Lambda 或匿名内部类注册监听器,无需额外定义监听器接口:
-
Lambda 注册:
bus.subscribe(UserLoginEvent.class, e -> System.out.println("Login: " + e.getUserId())); -
方法引用:
bus.subscribe(OrderPaidEvent.class, this::onOrderPaid); -
组合监听器:
bus.subscribe(LogEvent.class, logHandler.andThen(backupHandler));
支持异步发布与线程安全增强
基础版本是同步调用,生产中常需异步解耦。可扩展一个 AsyncEventBus,底层用 CompletableFuture.runAsync 或自定义线程池:
public class AsyncEventBus extends EventBus {
private final ExecutorService executor = Executors.newCachedThreadPool();
@Override
public <t> void publish(T event) {
List<consumer>> handlers = listeners.get(event.getClass());
if (handlers != null) {
handlers.forEach(h -> CompletableFuture.runAsync(
() -> ((Consumer<t>) h).accept(event), executor
));
}
}
}
</t></consumer></t>
注意:若监听器含状态或依赖外部资源,需自行保证其线程安全性;事件对象本身仍应保持不可变。
进阶:支持事件继承关系与通配监听
默认按 getClass() 精确匹配。如需支持父子事件类型(例如 PaymentEvent 继承自 BusinessEvent),可改用 Class.isAssignableFrom 查找匹配监听器:
public <t> void publish(T event) {
Class> eventType = event.getClass();
listeners.forEach((cls, handlers) -> {
if (cls.isAssignableFrom(eventType)) {
handlers.forEach(h -> ((Consumer<t>) h).accept(event));
}
});
}
</t></t>
这样注册 bus.subscribe(BusinessEvent.class, ...) 就能接收所有子类事件,更贴近真实业务场景。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











