大白话说Java设计模式-37-中介者模式(源码剖析篇)

📌 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 个核心要点)

  1. Spring MulticasteraddApplicationListener + multicastEvent 中介者协调。
  2. JDK Executorexecute(Runnable) 任务中介者。
  3. JDK ExecutorServicesubmit + invokeAll 扩展中介者。
  4. 设计哲学任务与执行分离 + 同事解耦 + 集中调度
  5. 借鉴价值事件中介者 / 任务中介者 / 服务中介者任何"多对象协调"都用中介者

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 个问题:

  1. 商品分页 / 树形菜单 / 文件夹怎么遍历?
  2. 迭代器 vs for 循环 / Stream 怎么区分?
  3. JDK 的 Iterator 怎么用?
  4. Java 8 Stream 怎么借鉴迭代器?

并附完整的商品遍历实战代码(含迭代器 + 聚合 + 单元测试),可直接复制到 IDEA 跑


觉得对您有帮助,麻烦 点点关注啦 ,您的关注是我创作的最大动力~ 🎯

相关推荐
焦虑的说说1 小时前
虚拟线程浅析
java
摇滚侠1 小时前
《SpringBoot 3:入门与应用实战》第 7 章 AOP 思想与实现 阅读笔记 13
java·spring boot·笔记
Mr. zhihao1 小时前
线上卡顿排查决策手册:场景 × 命令 × 现象 × 调整方案
java·开发语言·jvm
FYKJ_20101 小时前
springboot网上购书商城---附源码15749
java·spring boot·后端·python·spark·django·php
LayZhangStrive2 小时前
Java IDEA - 各种快捷键设置汇总(提高工具使用效率)
java·idea·设置·快捷键
snow@li2 小时前
Java:事务管理全景梳理/解决业务系统数据一致性问题
java
额额额对了2 小时前
Linux 进程管理详解:从概念到实战
java·服务器·前端
evans在进步2 小时前
Spring Boot 启动流程与 @SpringBootApplication 核心原理详解
java·spring boot·后端