多态是插件式架构真正解耦的核心机制,关键在于主业务代码完全不感知插件具体类型,仅依赖小而稳的接口(如log()、flush()),运行时动态绑定,参数用DTO、返回值语义明确,生命周期由宿主统一托管并注入PluginContext。

多态是插件式架构真正解耦的核心机制,关键不是“写了接口”,而是让主业务代码完全不感知插件的具体类型——调用时只认接口,运行时才决定执行谁。
定义小而稳的插件接口
接口要聚焦“做什么”,而非“怎么做”。例如日志插件只需声明 log(Level, String) 和 flush(),不掺杂配置加载、线程管理等实现细节。这样不同实现(写文件、发 HTTP、存数据库)可自由演进,主程序无需改动。
- 方法参数优先用不可变对象或 DTO,避免暴露具体集合类型(如不用
ArrayList,改用List) - 返回值明确语义,比如成功返回
Result.success(),失败返回Result.fail(code, msg) - 接口发布后尽量不增删方法;需扩展时,用默认方法或新增子接口(如
AsyncPlugin extends Plugin)
运行时绑定,编译期零耦合
主流程中所有插件引用必须是接口类型,比如 Plugin plugin = loader.load("auth-plugin"); plugin.execute();。JVM 在运行时自动分派到真实实现类,编译阶段不依赖任何插件的 class 文件。
- 禁止在业务代码里出现
instanceof、强制转型或new EncryptPlugin()这类硬编码 - 工厂或加载器返回值必须是接口类型,不能是具体类名字符串或 Class 对象
- 插件标识建议用逻辑名称(如
"payment-alipay"),而非全限定类名,防止编译期耦合
加载与生命周期由宿主统一托管
插件不是启动就全量加载,而是按需动态发现、实例化、初始化和销毁。宿主提供标准三阶段生命周期:initialize() → execute() → shutdown(),并支持启用/禁用开关和健康检查。
立即学习“Java免费学习笔记(深入)”;
- 推荐用
ServiceLoader或配置驱动(YAML 中声明plugins: ["log-file", "metric-prometheus"]) - 加载失败应记录警告并跳过,不影响其他插件;执行异常需捕获封装,不抛出未声明的 checked exception
- 每个插件独立管理资源(如连接池、缓存),异常不得穿透主线程
通过上下文注入能力,避免全局依赖
插件不该自己去 new Logger 或调用 SpringContext.getBean()。宿主在创建插件实例时,统一注入一个 PluginContext,里面封装配置读取、指标上报、事件发布等能力。
-
PluginContext应遵循接口隔离原则,比如拆分为ConfigReader、MetricsReporter等细粒度接口 - 插件内部不持有静态状态,所有共享数据均通过上下文传入,便于单元测试和并发安全
- 关键流程可预留钩子(如
beforeExecute()),插件选择性参与,不侵入主逻辑


















