📌 PDF :AI人工智能 --- 大模型微调与部署实战项目
大白话说Java设计模式-37-中介者模式(源码剖析篇):JDK / Spring 中的中介者实现
📌 一句话本质:中介者在源码里不是"协调多对象"的形象化,而是"事件 + 监听器 + 广播器"三件套的工业级架构。
🏷️ 标签:中介者模式 / ApplicationEventMulticaster / Executor / ExecutorService 🎯 适合:中高级后端 / 想读懂主流框架源码的工程师
目录
- 一、为什么读中介者源码?一张地图先看清
- [二、Spring 源码剖析:ApplicationEventMulticaster 事件中介者](#二、Spring 源码剖析:ApplicationEventMulticaster 事件中介者)
- [三、JDK 源码剖析:Executor 任务中介者](#三、JDK 源码剖析:Executor 任务中介者)
- [四、Java Concurrency 源码剖析:ExecutorService](#四、Java Concurrency 源码剖析:ExecutorService)
- 五、为什么框架作者这么设计?
- [六、借鉴到我们项目:3 个"抄作业"实践](#六、借鉴到我们项目:3 个"抄作业"实践)
- [七、本篇小结 + 下一模式预告](#七、本篇小结 + 下一模式预告)
一、为什么读中介者源码?一张地图先看清
中介者模式在 JDK 和 Spring 里出现得最经典 ------ApplicationEventMulticaster / Executor / ExecutorService 都是中介者思想。
源码地图:
| 类别 | 框架 / 中间件 | 中介者接口 | 同事 |
|---|---|---|---|
| Spring | context.event |
ApplicationEventMulticaster |
ApplicationListener |
| JDK | java.util.concurrent |
Executor |
Runnable |
| JDK | java.util.concurrent |
ExecutorService |
Callable |
| Jetty | org.eclipse.jetty |
Server |
Handler |
| Tomcat | org.apache.catalina |
Connector |
Container |
我们按"Multicaster → Executor → ExecutorService"的顺序来剖析。
二、Spring 源码剖析:ApplicationEventMulticaster 事件中介者
2.1 ApplicationEventMulticaster:中介者接口
源码位置:
- Spring Framework 6.1.x
spring-context/src/main/java/org/springframework/context/event/ApplicationEventMulticaster.java
核心源码:
java
/**
* ✅ 事件中介者:广播器
*/
public interface ApplicationEventMulticaster {
/**
* ✅ 添加监听器(注册同事)
*/
void addApplicationListener(ApplicationListener<?> listener);
/**
* 移除监听器
*/
void removeApplicationListener(ApplicationListener<?> listener);
/**
* 移除所有
*/
void removeAllListeners();
/**
* ✅ 广播事件(中介者协调)
*/
void multicastEvent(ApplicationEvent event);
/**
* 广播事件(带类型)
*/
void multicastEvent(ApplicationEvent event, ResolvableType eventType);
}
关键点:
| 关键点 | 解释 |
|---|---|
addApplicationListener |
注册同事 |
multicastEvent |
中介者协调 |
ResolvableType |
类型匹配 |
| 解耦 | 同事不互相知道 |
2.2 SimpleApplicationEventMulticaster:默认中介者
核心源码:
java
/**
* ✅ 默认中介者实现
*/
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
@Nullable
private Executor taskExecutor;
@Nullable
private ErrorHandler errorHandler;
@Override
public void multicastEvent(ApplicationEvent event) {
multicastEvent(event, resolveDefaultEventType(event));
}
@Override
public void multicastEvent(ApplicationEvent event, ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
// ✅ 中介者协调
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
// 异步
executor.execute(() -> invokeListener(listener, event));
} else {
// 同步
invokeListener(listener, event);
}
}
}
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
doInvokeListener(listener, event);
} catch (Throwable err) {
errorHandler.handleError(err);
}
} else {
doInvokeListener(listener, event);
}
}
}
关键点:
| 关键点 | 解释 |
|---|---|
getApplicationListeners() |
找到所有匹配监听器 |
Executor |
异步执行 |
ErrorHandler |
异常隔离 |
| 中介者协调 | 统一调度 |
2.3 AbstractApplicationEventMulticaster:同事管理
核心源码:
java
/**
* ✅ 中介者基类:管理同事
*/
public abstract class AbstractApplicationEventMulticaster
implements ApplicationEventMulticaster, ... {
/**
* ✅ 同事缓存
*/
private final ListenerRetriever defaultRetriever = new ListenerRetriever();
@Override
public void addApplicationListener(ApplicationListener<?> listener) {
synchronized (this.defaultRetriever) {
this.defaultRetriever.applicationListeners.add(listener);
}
}
/**
* ✅ 根据事件类型找匹配监听器
*/
protected Collection<ApplicationListener<?>> getApplicationListeners(
ApplicationEvent event, ResolvableType eventType) {
// 1️⃣ 获取所有监听器
// 2️⃣ 根据事件类型过滤
// 3️⃣ 返回匹配的监听器
}
}
2.4 完整中介者调用链
OrderService.publishEvent(event)
↓
ApplicationContext.publishEvent(event)
↓
ApplicationEventMulticaster.multicastEvent(event)
↓
1️⃣ getApplicationListeners(event, type)
↓ 找到所有匹配监听器
2️⃣ 遍历 listeners
3️⃣ listener.onApplicationEvent(event)
↓
StockListener / PointsListener / LogisticsListener / ...
2.5 ApplicationEventMulticaster 的"作者选择"
| 设计点 | 选择 | 原因 |
|---|---|---|
| 接口分离 | Multicaster / Listener | 单一职责 |
| 异步支持 | Executor | 性能 |
| 异常隔离 | ErrorHandler | 不影响主流程 |
| 监听器缓存 | ListenerRetriever | 性能 |
| 类型匹配 | ResolvableType | 灵活 |
三、JDK 源码剖析:Executor 任务中介者
3.1 Executor:中介者接口
源码位置:
- OpenJDK 17
src/java.base/share/classes/java/util/concurrent/Executor.java
核心源码:
java
/**
* ✅ 任务中介者:执行器
*/
public interface Executor {
/**
* ✅ 执行任务(中介者协调)
*/
void execute(Runnable command);
}
关键点:
| 关键点 | 解释 |
|---|---|
execute(Runnable) |
中介者协调 |
| 单一方法 | 函数式接口 |
| 任务与执行分离 | 解耦 |
3.2 ThreadPoolExecutor:线程池中介者
核心源码(简化版):
java
/**
* ✅ 线程池中介者
*/
public class ThreadPoolExecutor extends AbstractExecutorService {
private final BlockingQueue<Runnable> workQueue;
private final ReentrantLock mainLock = new ReentrantLock();
/**
* ✅ 中介者协调
*/
@Override
public void execute(Runnable command) {
if (command == null) throw new NullPointerException();
int c = ctl.get();
// 1️⃣ 中介者路由:核心线程优先
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true)) return;
}
// 2️⃣ 中介者路由:入队
if (workQueue.offer(command)) {
if (!isRunning(c)) {
reject(command);
}
}
// 3️⃣ 中介者路由:非核心线程
else if (!addWorker(command, false)) {
reject(command); // 拒绝
}
}
}
关键点:
| 关键点 | 解释 |
|---|---|
| 核心线程 | 优先创建 |
| 工作队列 | 排队 |
| 非核心线程 | 队列满时 |
| 拒绝策略 | 兜底 |
3.3 完整中介者调用链
executor.execute(command)
↓
ThreadPoolExecutor.execute()
↓ 中介者协调
1. 线程数 < corePoolSize?
├── 是 → addWorker(command, true) // 核心线程
└── 否
↓
2. 队列未满?
├── 是 → workQueue.offer(command) // 入队
└── 否
↓
3. 线程数 < maxPoolSize?
├── 是 → addWorker(command, false) // 非核心线程
└── 否
↓
4. 拒绝策略
3.4 Executor 的"作者选择"
| 设计点 | 选择 | 原因 |
|---|---|---|
| 接口分离 | Executor / ExecutorService | 单一职责 |
| 任务与执行分离 | execute() | 解耦 |
| 线程池 | 复用线程 | 性能 |
| 拒绝策略 | 4 种 | 灵活 |
四、Java Concurrency 源码剖析:ExecutorService
4.1 ExecutorService:扩展中介者
核心源码:
java
/**
* ✅ 扩展中介者
*/
public interface ExecutorService extends Executor, AutoCloseable {
/**
* ✅ 中介者协调:提交任务
*/
<T> Future<T> submit(Callable<T> task);
Future<?> submit(Runnable task);
<T> Future<T> submit(Runnable task, T result);
/**
* 中介者协调:批量执行
*/
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException;
/**
* 关闭
*/
void shutdown();
}
关键点:
| 关键点 | 解释 |
|---|---|
submit() |
中介者接收任务 |
Future |
任务结果 |
invokeAll |
批量协调 |
shutdown |
关闭中介者 |
4.2 AbstractExecutorService:中介者基类
核心源码:
java
/**
* ✅ 中介者基类
*/
public abstract class AbstractExecutorService implements ExecutorService {
/**
* ✅ 中介者协调:newTaskFor
*/
protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
return new FutureTask<T>(runnable, value);
}
/**
* 中介者协调:submit
*/
public Future<?> submit(Runnable task) {
RunnableFuture<Void> ftask = newTaskFor(task, null);
execute(ftask);
return ftask;
}
}
4.3 ScheduledThreadPoolExecutor:定时中介者
核心源码:
java
/**
* ✅ 定时中介者
*/
public class ScheduledThreadPoolExecutor extends ThreadPoolExecutor
implements ScheduledExecutorService {
/**
* ✅ 中介者协调:定时执行
*/
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
// 1️⃣ 包装为 ScheduledFutureTask
RunnableScheduledFuture<Void> ftask = new ScheduledFutureTask<Void>(
command, null, triggerTime(delay, unit));
// 2️⃣ 加入延迟队列
delayedExecute(ftask);
return ftask;
}
}
4.4 ExecutorService 的"作者选择"
| 设计点 | 选择 | 原因 |
|---|---|---|
| 接口扩展 | Executor → ExecutorService | 扩展 |
| Future 模式 | 异步结果 | 灵活 |
| invokeAll | 批量提交 | 高效 |
| shutdown | 生命周期管理 | 优雅关闭 |
五、为什么框架作者这么设计?
读源码看的是"实现",悟的是"设计哲学"。
5.1 框架作者选中介者的 4 个核心考虑
| 序号 | 考虑 | 举例 |
|---|---|---|
| ① | 多对象协调 | 事件/任务 |
| ② | 解耦同事 | 同事之间不互调 |
| ③ | 集中调度 | 中介者统一 |
| ④ | 异步支持 | 不阻塞主流程 |
5.2 中介者 vs 外观:源码里怎么选?
| 场景 | 选哪个 | 原因 |
|---|---|---|
| 多对象协调 | 中介者 | 双向通信 |
| 单向简化 | 外观 | 简化接口 |
| 事件广播 | 中介者 | 多对多 |
| API 封装 | 外观 | 统一入口 |
5.3 框架作者不选中介者的 3 种情况
| 序号 | 场景 | 原因 |
|---|---|---|
| ① | 单一对象 | 直接调 |
| ② | 简单调用 | 没必要 |
| ③ | 性能关键 | 中介者开销 |
5.4 中介者在企业级应用的 3 种典型用法
用法 1:事件中介者
Spring ApplicationEventMulticaster
→ 多监听器协调
用法 2:任务中介者
Executor / ExecutorService
→ 多任务调度
用法 3:服务中介者
API Gateway
→ 多服务协调
六、借鉴到我们项目:3 个"抄作业"实践
6.1 实践 1:自定义事件中介者
场景:大白商城内部事件(订单/支付/库存/物流协调)。
完整实现:
java
/**
* 借鉴 Spring Multicaster:自定义事件中介者
*/
public class DabaiEventMulticaster {
/**
* ✅ 中介者持有所有监听器
*/
private final Map<Class<?>, List<Consumer<?>>> handlerMap = new ConcurrentHashMap<>();
/**
* ✅ 注册同事
*/
public <T> void register(Class<T> eventType, Consumer<T> handler) {
handlerMap.computeIfAbsent(eventType, k -> new CopyOnWriteArrayList<>())
.add(handler);
}
/**
* ✅ 中介者协调
*/
@SuppressWarnings("unchecked")
public <T> void publish(T event) {
List<Consumer<?>> handlers = handlerMap.get(event.getClass());
if (handlers != null) {
for (Consumer<?> handler : handlers) {
try {
((Consumer<T>) handler).accept(event);
} catch (Exception e) {
log.error("事件处理失败: {}", event, e);
}
}
}
}
}
// 使用
eventMulticaster.register(OrderPaidEvent.class, e -> {
log.info("库存扣减: {}", e.getOrderId());
});
eventMulticaster.register(OrderPaidEvent.class, e -> {
log.info("积分增加: {}", e.getUserId());
});
eventMulticaster.publish(new OrderPaidEvent(...));
6.2 实践 2:任务调度中介者
场景:大白商城异步任务(发短信/发邮件/导出报表)。
完整实现:
java
/**
* 借鉴 Executor:任务调度中介者
*/
public class TaskMediator {
private final ExecutorService executor;
private final ExecutorService scheduledExecutor;
public TaskMediator() {
this.executor = Executors.newFixedThreadPool(20);
this.scheduledExecutor = Executors.newScheduledThreadPool(5);
}
/**
* ✅ 提交任务
*/
public Future<?> submit(Runnable task) {
return executor.submit(task);
}
/**
* ✅ 定时任务
*/
public ScheduledFuture<?> schedule(Runnable task, long delay, TimeUnit unit) {
return scheduledExecutor.schedule(task, delay, unit);
}
/**
* ✅ 批量任务
*/
public <T> List<T> submitBatch(List<Callable<T>> tasks) {
try {
List<Future<T>> futures = executor.invokeAll(tasks);
return futures.stream()
.map(this::getResult)
.toList();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return Collections.emptyList();
}
}
private <T> T getResult(Future<T> future) {
try {
return future.get(30, TimeUnit.SECONDS);
} catch (Exception e) {
return null;
}
}
}
6.3 实践 3:多服务协调中介者
场景:大白商城订单全链路协调(订单/支付/库存/物流/积分/通知)。
完整实现:
java
/**
* 借鉴 ApplicationEventMulticaster:多服务协调
*/
public class ServiceCoordinator {
/**
* ✅ 服务集合
*/
private final Map<String, ServiceHandler> services = new ConcurrentHashMap<>();
public void register(String serviceName, ServiceHandler handler) {
services.put(serviceName, handler);
}
/**
* ✅ 中介者协调
*/
public Object coordinate(String fromService, String toService, Object request) {
ServiceHandler handler = services.get(toService);
if (handler == null) {
throw new IllegalArgumentException("未知服务: " + toService);
}
return handler.handle(fromService, request);
}
}
@FunctionalInterface
public interface ServiceHandler {
Object handle(String fromService, Object request);
}
// 使用
ServiceCoordinator coordinator = new ServiceCoordinator();
coordinator.register("payment", (from, req) -> {
log.info("处理支付: from={}, req={}", from, req);
return "payment result";
});
coordinator.register("stock", (from, req) -> {
log.info("处理库存: from={}, req={}", from, req);
return "stock result";
});
// 订单服务协调
coordinator.coordinate("order", "payment", "pay order 001");
coordinator.coordinate("order", "stock", "decrease stock 001");
收益:
| 优化点 | 效果 |
|---|---|
| 事件中介者 | 自定义事件统一处理 |
| 任务中介者 | 异步任务统一调度 |
| 服务中介者 | 多服务集中协调 |
七、本篇小结 + 下一模式预告
7.1 本篇小结(5 个核心要点)
- Spring Multicaster :
addApplicationListener+multicastEvent中介者协调。 - JDK Executor :
execute(Runnable)任务中介者。 - JDK ExecutorService :
submit+invokeAll扩展中介者。 - 设计哲学 :任务与执行分离 + 同事解耦 + 集中调度。
- 借鉴价值 :事件中介者 / 任务中介者 / 服务中介者 ,任何"多对象协调"都用中介者。
7.2 一句话总结
中介者在源码里不是"协调多对象"的形象化,而是"事件 + 监听器 + 广播器"三件套的工业级架构 。ApplicationEventMulticaster 协调事件,Executor 协调任务,ExecutorService 协调批量任务。学中介者,先学 Spring Multicaster。
7.3 知识脑图
中介者源码剖析
├── Spring
│ ├── ApplicationEventMulticaster(事件中介者)
│ │ ├── SimpleApplicationEventMulticaster
│ │ └── AbstractApplicationEventMulticaster
│ ├── ApplicationListener(同事)
│ └── ApplicationEventPublisher
├── JDK
│ ├── Executor(任务中介者)
│ │ ├── ThreadPoolExecutor
│ │ ├── ScheduledThreadPoolExecutor
│ │ └── ForkJoinPool
│ ├── ExecutorService(扩展中介者)
│ └── AbstractExecutorService
└── 借鉴价值
├── 事件中介者
├── 任务中介者
└── 服务中介者
7.4 下一模式预告
第 38 篇【迭代器模式 - 业务实战篇】:大白商城商品分页游标的"遍历封装"
下一篇我们会实战迭代器模式,回答 4 个问题:
- 商品分页 / 树形菜单 / 文件夹怎么遍历?
- 迭代器 vs for 循环 / Stream 怎么区分?
- JDK 的
Iterator怎么用? - Java 8
Stream怎么借鉴迭代器?
并附完整的商品遍历实战代码(含迭代器 + 聚合 + 单元测试),可直接复制到 IDEA 跑。
觉得对您有帮助,麻烦 点点关注啦 ,您的关注是我创作的最大动力~ 🎯