跳到主要内容
📖 本章预览

本章为预览版本,展示部分核心内容。完整内容包含详细源码解析、实战代码和面试要点,加入知识星球即可解锁全部章节。

第十章:不 fork 源码就能扩展框架的所有能力 — 全方位 SPI 机制

本章目标:理解 ExtensionServiceLoader 的统一加载机制,掌握 8 大 SPI 扩展点的源码位置和扩展方式,学会自定义采集器和通知器。


10.1 问题场景

一个框架再完善,也无法覆盖所有业务场景。比如:

  • 你想把监控指标推到自研的监控系统
  • 你想用企业内部的 IM 发告警
  • 你想在任务提交时注入自定义上下文

如果框架不提供扩展点,你只能 fork 源码改,升级时痛苦万分。

DynamicTP 基于 JDK ServiceLoader 封装了统一的 SPI 加载器,几乎所有核心组件都支持 SPI 扩展。用户只需在 META-INF/services 下添加实现类,框架自动加载,零侵入。


10.2 ExtensionServiceLoader 统一加载器

public class ExtensionServiceLoader {

// 全局缓存,避免重复加载
private static final Map<Class<?>, List<?>> EXTENSION_MAP =
new ConcurrentHashMap<>();

/**
* 加载指定接口的所有 SPI 实现
* 第一次加载后缓存,后续直接返回
*/
@SuppressWarnings("unchecked")
public static <T> List<T> get(Class<T> clazz) {
List<T> services = (List<T>) EXTENSION_MAP.get(clazz);
if (CollectionUtils.isEmpty(services)) {
services = load(clazz);
if (CollectionUtils.isNotEmpty(services)) {
EXTENSION_MAP.put(clazz, services);
}
}
return services;
}

/**
* 只取第一个实现(适用于"替换默认实现"的场景)
*/
public static <T> T getFirst(Class<T> clazz) {
List<T> services = get(clazz);
return CollectionUtils.isEmpty(services) ? null : services.get(0);
}

/**
* 底层委托 JDK ServiceLoader
*/
private static <T> List<T> load(Class<T> clazz) {
ServiceLoader<T> serviceLoader = ServiceLoader.load(clazz);
List<T> services = new ArrayList<>();
for (T service : serviceLoader) {
services.add(service);
}
return services;
}
}

设计要点:

  • ConcurrentHashMap 缓存:同一接口只加载一次,避免重复扫描 classpath
  • get() 返回列表(多个实现叠加),getFirst() 返回第一个(替换默认实现)
  • 对 JDK ServiceLoader 的薄封装,保持简洁

10.3 八大 SPI 扩展点

1. 监控采集器 — MetricsCollector

// CollectorHandler 构造函数中
List<MetricsCollector> loadedCollectors =
ExtensionServiceLoader.get(MetricsCollector.class);

扩展场景:推送到自研监控系统、写入 InfluxDB、发送到 Kafka

2. 通知器 — DtpNotifier

// NotifierHandler 构造函数中
List<DtpNotifier> loadedNotifiers =
ExtensionServiceLoader.get(DtpNotifier.class);

扩展场景:对接企业内部 IM、邮件通知、短信告警

3. 任务包装器 — TaskWrapper

// TaskWrappers 构造函数中
List<TaskWrapper> loadedWrappers =
ExtensionServiceLoader.get(TaskWrapper.class);

扩展场景:链路追踪上下文传递、SecurityContext 传递


🔒 解锁完整内容

本章剩余内容需要解锁后查看

以上仅为本章部分预览内容,完整内容包含更多深度源码解析、实战代码和面试要点。

加入知识星球你将获得:

  • ✅ 全部 12 章完整内容 + 持续更新
  • ✅ 配套源码 + 实战项目
  • ✅ 一对一答疑 + 面试辅导
  • ✅ 简历优化 + 内推机会

📚 本章完整目录

以下为本章完整目录结构,加入知识星球即可解锁全部内容。

4. 拒绝策略 — RejectedExecutionHandler

5. 生命周期感知 — ExecutorAware

6. 配置解析器 — ConfigParser

7. 插件拦截器 — DtpInterceptor

8. 初始化器 — DtpInitializer

10.4 扩展实战:自定义 Kafka 采集器

10.5 扩展实战:自定义企业 IM 通知器

10.6 SPI 扩展点全景