LiteFlow 框架分析系列(二):Core 核心模块深度解析

请关注公众号【碳硅化合物AI

摘要

上一篇我们宏观了解了 LiteFlow 的工作原理,本篇将深入 liteflow-core 模块,像剥洋葱一样拆解其核心实现。我们将重点分析流程执行入口 FlowExecutor、元数据容器 FlowBus、执行单元 NodeComponent 以及数据管理 DataBus

1. 核心类关系图

在开始代码分析前,先通过一张类图理清核心组件之间的关系:
image.png

2. 流程执行入口:FlowExecutor

FlowExecutor 是 LiteFlow 对外暴露的主要入口。不管是 Spring Boot 启动时的初始化,还是运行时发起流程调用,都离不开它。

2.1 初始化 (init)

FlowExecutor 的构造函数或 init 方法会触发整个框架的启动。主要做了这几件事:

  1. 上下文初始化ContextCmpInitHolder.loadContextCmpInit().initCmp(),扫描并注册组件。
  2. 解析规则:根据配置的 rule-source(如 flow.el.xml),找到对应的 FlowParser 进行解析。解析后的 Chain 和 Node 会被存入 FlowBus
  3. 初始化 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:

  1. chainMap: 存储所有解析好的流程链。
  2. 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 的设计非常精炼:

  1. FlowExecutor 负责流程调度和资源申请。
  2. FlowBus 负责管理元数据(Chain/Node),提供热刷新能力。
  3. DataBus 通过池化技术高效管理数据上下文(Slot)。
  4. NodeComponent 封装了业务逻辑和生命周期。

这一套组合拳打下来,既保证了扩展性(组件化),又保证了高性能(池化、轻量级传递)。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐