一个订单处理方法,50 行起步,三轮需求迭代后膨胀到 500 行。六层 if-else 嵌套,硬编码的分支散落各处,改一处怕崩一片——这是做复杂业务的 Java 开发者迟早会撞上的墙。Solon Flow 把这类流程编排问题从"方法体内嵌套"拉出来,变成可定义、可追踪、可热更新的链路结构,覆盖规则引擎、任务编排、工作流和 AI Agent 编排全场景。
业务代码膨胀的根因
问题不在于需求多,在于分支逻辑和执行顺序被锁在方法体里。每加一条规则,就多一层判断;每改一个步骤顺序,就要在嵌套深处挪代码。结果是:
- 执行路径隐式依赖调用顺序,没人能一眼看清完整链路。
- 分支条件散落在不同层级,测试只能覆盖走到的路径。
- 新人看不懂,老人不敢改,知识传承靠口口相传。
本质上是流程定义和业务实现混在一起,流程变了就得改实现代码。Solon Flow 的思路:把流程定义抽出来,用链式结构描述"做什么、什么条件下做、做完下一步做什么",业务组件只负责"怎么做"。
Solon Flow 的编排模型
Solon Flow 的核心是 Chain + Node + Condition 三层结构:
- Chain:一条完整链路,比如"订单审批流程"。
- Node:链路上的一个执行节点,绑定一个业务组件。
- Condition:节点间的条件连接,决定走哪条分支。
一条 Chain 可以是线性链路,也可以带条件分支、并行分支、循环甚至子链路嵌套。定义方式支持 DSL 声明式和 Java 流式 API 两种,下面用流式 API 举例——对 Java 开发者来说上手更自然。
实战:用 Solon Flow 重构订单审批链路
假设原来的订单审批逻辑是这样的伪代码:
// 原始写法:层层嵌套
public OrderResult processOrder(Order order) {
if (!stockService.check(order)) {
return OrderResult.fail("库存不足");
}
if (order.getAmount() > 10000) {
if (!riskService.review(order)) {
return OrderResult.fail("风控拒绝");
}
if (!managerService.approve(order)) {
return OrderResult.fail("主管未批");
}
}
if (!paymentService.charge(order)) {
return OrderResult.fail("支付失败");
}
return OrderResult.ok();
}
用 Solon Flow 改写后,流程定义和业务组件分离:
// 1. 定义 Chain(流程结构)
Chain orderChain = Chain.of("orderProcess")
.node("n1", "stockCheck") // 库存校验
.node("n2", "riskReview") // 风控审核(条件触发)
.node("n3", "managerApprove") // 主管审批(条件触发)
.node("n4", "paymentCharge") // 支付扣款
// 连接关系与条件
.link("n1", "n2").when(ctx -> ctx.order.getAmount() > 10000)
.link("n1", "n4").when(ctx -> ctx.order.getAmount() <= 10000)
.link("n2", "n3").when(ctx -> ctx.result("n2").isPass())
.link("n2", "n4").when(ctx -> ctx.result("n2").isReject())
.link("n3", "n4").when(ctx -> ctx.result("n3").isPass())
.build();
// 2. 注册业务组件(只管"怎么做")
FlowEngine engine = new FlowEngine();
engine.register("stockCheck", ctx -> {
boolean ok = stockService.check(ctx.order);
ctx.result(ok ? "pass" : "fail");
});
engine.register("riskReview", ctx -> {
boolean ok = riskService.review(ctx.order);
ctx.result(ok ? "pass" : "reject");
});
engine.register("managerApprove", ctx -> {
boolean ok = managerService.approve(ctx.order);
ctx.result(ok ? "pass" : "fail");
});
engine.register("paymentCharge", ctx -> {
boolean ok = paymentService.charge(ctx.order);
ctx.result(ok ? "pass" : "fail");
});
// 3. 执行
FlowContext ctx = new FlowContext();
ctx.order = order;
engine.run(orderChain, ctx);
关键变化:
- 流程结构一眼可见:
link+when把分支条件显式声明,不再藏在 if-else 深处。 - 业务组件独立:
stockCheck、riskReview各自只处理一件事,可单独测试。 - 分支条件可追踪:
when里的条件表达式是链路元数据,可以导出、可视化、做审计。
超越简单分支:规则、任务、工作流、AI 编排
Solon Flow 不只是把 if-else 拉平。它的 Chain 模型能承载四种典型场景:
| 场景 | 特征 | Solon Flow 对应 |
|---|---|---|
| 规则引擎 | 条件多、优先级敏感 | 条件链路 + 优先级排序 |
| 任务编排 | 步骤顺序固定、有并行节点 | 线性链 + 并行分支 |
| 工作流 | 人工审批节点、状态持久化 | 链路 + 等待节点 + 状态恢复 |
| AI Agent 编排 | LLM 调用、工具选择、多轮对话 | 链路 + 动态节点 + 上下文传递 |
以 AI Agent 编排为例,一个简单的"用户提问 → LLM 判断意图 → 调用对应工具 → 返回结果"链路可以这样搭:
Chain agentChain = Chain.of("customerAgent")
.node("n1", "llmIntent") // LLM 分析意图
.node("n2", "queryOrderTool") // 查订单工具
.node("n3", "refundTool") // 退款工具
.node("n4", "llmReply") // LLM 生成回复
.link("n1", "n2").when(ctx -> "query_order".equals(ctx.intent))
.link("n1", "n3").when(ctx -> "refund".equals(ctx.intent))
.link("n2", "n4")
.link("n3", "n4")
.build();
engine.register("llmIntent", ctx -> {
String intent = llmClient.analyze(ctx.userMessage);
ctx.intent = intent;
});
engine.register("queryOrderTool", ctx -> {
ctx.toolResult = orderService.query(ctx.userMessage);
});
engine.register("refundTool", ctx -> {
ctx.toolResult = refundService.process(ctx.userMessage);
});
engine.register("llmReply", ctx -> {
ctx.reply = llmClient.generate(ctx.toolResult);
});
LLM 调用、工具选择、结果回传——全部在链路里显式编排,不再需要在 Agent 类里写一堆 if-else 判断意图再选工具。
上手前需要想清楚的几件事
什么时候该引入流程编排? 不是所有业务都需要。如果你的流程只有两三个步骤、没有条件分支、不会频繁变化,直接写方法调用就够了。引入编排框架有学习成本和运行开销,别为了优雅过度设计。
DSL 还是 Java API? Solon Flow 支持 DSL 声明式定义,适合需要可视化编辑、非开发人员参与配置的场景。如果流程变更主要由开发团队控制,Java 流式 API 更直接,IDE 支持也更好。
状态持久化怎么做? 工作流场景需要暂停等待(比如等主管审批),链路执行到一半要能存下来、恢复后继续跑。Solon Flow 提供了状态持久化机制,但具体存储选型(数据库、缓存)需要根据业务量级决定。
性能边界在哪? 流程编排引入了一层引擎调度,每个节点执行有一次上下文传递开销。对高频低延迟场景(比如每秒万级的实时计算),要评估这层开销是否可接受。复杂业务流程通常不是高频场景,这个开销可以忽略。
迁移策略: 不要一次性把所有业务重写。挑一个最痛的流程(那个 500 行的方法)先试点,用 Solon Flow 重构后跑一段时间,确认链路追踪和可维护性确实改善,再逐步推广。
Solon Flow 解决的不是"代码怎么写更漂亮"的问题,而是业务流程怎么定义、怎么变更、怎么追踪的问题。当你的 if-else 已经嵌套到没人敢动的时候,把流程定义从方法体里抽出来,用 Chain + Node + Condition 重新描述,是值得认真评估的方向。