LiteFlow 框架分析系列(二):Core 核心模块深度解析
负责流程调度和资源申请。FlowBus负责管理元数据(Chain/Node),提供热刷新能力。DataBus通过池化技术高效管理数据上下文(Slot)。封装了业务逻辑和生命周期。这一套组合拳打下来,既保证了扩展性(组件化),又保证了高性能(池化、轻量级传递)。
LiteFlow 框架分析系列(二):Core 核心模块深度解析
请关注公众号【碳硅化合物AI】
摘要
上一篇我们宏观了解了 LiteFlow 的工作原理,本篇将深入 liteflow-core 模块,像剥洋葱一样拆解其核心实现。我们将重点分析流程执行入口 FlowExecutor、元数据容器 FlowBus、执行单元 NodeComponent 以及数据管理 DataBus。
1. 核心类关系图
在开始代码分析前,先通过一张类图理清核心组件之间的关系:
2. 流程执行入口:FlowExecutor
FlowExecutor 是 LiteFlow 对外暴露的主要入口。不管是 Spring Boot 启动时的初始化,还是运行时发起流程调用,都离不开它。
2.1 初始化 (init)
FlowExecutor 的构造函数或 init 方法会触发整个框架的启动。主要做了这几件事:
- 上下文初始化:
ContextCmpInitHolder.loadContextCmpInit().initCmp(),扫描并注册组件。 - 解析规则:根据配置的
rule-source(如flow.el.xml),找到对应的FlowParser进行解析。解析后的 Chain 和 Node 会被存入FlowBus。 - 初始化 DataBus:预分配数据槽位。
2.2 执行流程 (execute2Resp)
这是最常用的执行方法。关键代码摘要:
public LiteflowResponse execute2Resp(String chainId, Object param, Class<?>... contextBeanClazzArray) {
// 1. 申请 Slot(数据槽)
Slot slot = doExecute(chainId, param, ..., ChainExecuteModeEnum.BODY);
return LiteflowResponse.newMainResponse(slot);
}
private Slot doExecute(...) {
// ... 省略部分代码 ...
// 2. 从 DataBus 获取 Slot 下标
Integer slotIndex = DataBus.offerSlotByClass(...);
Slot slot = DataBus.getSlot(slotIndex);
// 3. 查找 Chain
Chain chain = FlowBus.getChain(chainId);
// 4. 执行 Chain
chain.execute(slotIndex);
// 5. 释放 Slot
DataBus.releaseSlot(slotIndex);
return slot;
}
这里有个巧妙的设计:Slot Index。LiteFlow 并不直接在各组件间传递庞大的 Context 对象,而是传递一个轻量级的 Integer 下标。组件需要数据时,拿这个下标去 DataBus 换取真正的 Slot。
3. 交通枢纽:FlowBus
FlowBus 是一个静态类,充当了 LiteFlow 的“内存数据库”。它维护了两个核心 Map:
chainMap: 存储所有解析好的流程链。nodeMap: 存储所有的节点组件。
public class FlowBus {
private static final Map<String, Chain> chainMap;
private static final Map<String, Node> nodeMap;
// 动态添加 Chain
public static void addChain(Chain chain) { ... }
// 动态添加 Node
public static void addNode(...) { ... }
}
LiteFlow 的热刷新功能,本质上就是重新解析规则,然后更新 FlowBus 里的这两个 Map。
4. 执行单元:NodeComponent
NodeComponent 是所有业务组件的基类。你自己写的组件(比如 ACmp)都继承自它。
它定义了组件的生命周期:
isAccess(): 是否允许执行(可用于简单的准入判断)。process(): 核心业务逻辑(必须实现)。beforeProcess()/afterProcess(): 前置/后置钩子。onSuccess()/onError(): 成功/失败回调。isContinueOnError(): 出错是否继续(默认 false)。
在 NodeComponent 中,有个 self 属性很有意思:
private NodeComponent self;
这是为了解决 Spring AOP 代理问题。如果组件被代理了,this 指向的是原始对象,而 self 指向代理对象,确保切面能生效。
5. 数据中心:DataBus 与 Slot
LiteFlow 的高性能很大程度上归功于 DataBus 的设计。它解决了一个核心问题:高并发下的数据隔离与复用。
5.1 复用池机制
DataBus 内部维护了一个 Slot 池(默认 1024 个)。
- 结构:
ConcurrentHashMap<Integer, Slot>存数据,ConcurrentLinkedQueue<Integer>存空闲下标。 - 申请:
QUEUE.poll()拿一个下标,拿不到就扩容(1.75倍)。 - 释放:
QUEUE.add(index)归还下标。
这种池化设计避免了频繁创建和销毁 Context 对象,极大降低了 GC 压力。
5.2 Slot (槽)
Slot 是真正的上下文容器。它里面存放了:
requestData: 初始请求参数。contextBeanList: 用户定义的上下文 Bean(如 Spring 的 Bean 或普通的 Pojo)。dataMap: 内部传递数据的 Map。
6. 总结
liteflow-core 的设计非常精炼:
- FlowExecutor 负责流程调度和资源申请。
- FlowBus 负责管理元数据(Chain/Node),提供热刷新能力。
- DataBus 通过池化技术高效管理数据上下文(Slot)。
- NodeComponent 封装了业务逻辑和生命周期。
这一套组合拳打下来,既保证了扩展性(组件化),又保证了高性能(池化、轻量级传递)。
更多推荐


所有评论(0)