多步骤工作流向导中,用@StepDependency注解声明步骤依赖,通过卡恩算法检测环并DFS拓扑排序执行;支持条件过滤、动态跳过及UI状态联动反馈。

在多步骤工作流向导中,用自定义注解动态标记步骤依赖关系,本质是把业务逻辑的先后约束“声明化”,再通过运行时解析生成可执行的拓扑顺序。关键不在于注解本身,而在于它如何与步骤执行引擎联动——既要表达依赖(如 @DependsOn("step2")),又要支持循环检测、并行推导和异常反馈。
定义面向步骤的依赖注解
注解需明确表达两个信息:当前步骤依赖谁、是否强制等待(而非仅提示)。推荐使用 @StepDependency,而非泛化的 @DependsOn,避免与框架级依赖混淆。
-
@Target(ElementType.METHOD):限定只标注向导中的步骤处理方法,比如
confirmOrder()、sendNotification() - @Retention(RetentionPolicy.RUNTIME):确保运行时可通过反射读取
- 提供
value()字符串数组,支持多依赖,如@StepDependency({"validate", "fetchUser"}) - 可选
mode = DependencyMode.STRICT或WEAK,用于区分阻塞式依赖与建议式依赖
构建步骤图并执行拓扑排序
启动向导时,扫描所有带 @StepDependency 的方法,提取 method name → dependsOn list 映射,构造成有向图节点。此时不直接调用 DFS,而是先做两件事:
- 用卡恩算法(Kahn’s)做一次入度统计,快速识别是否存在环;若发现环,立即抛出
CircularStepDependencyException并附带路径(如 stepA → stepB → stepC → stepA) - 对无环图,用 DFS 前序遍历生成执行序列——注意:不是简单按依赖链深挖,而是从所有入度为 0 的“起始步骤”并发启动子图遍历,保证多个独立分支可并行初始化
运行时动态调整依赖关系
静态注解无法覆盖条件分支(例如“仅当用户等级 ≥ VIP 时才执行风控校验”)。这时需结合 Spring 的 @ConditionalOnProperty 或自定义 @StepCondition 注解,在拓扑排序前过滤节点。
- 将条件判断封装为
StepPredicate函数式接口,注册到步骤元数据中 - 排序前统一执行所有 predicate,剔除不满足条件的步骤及其出边,再重新计算入度
- 保留被跳过的步骤名到执行上下文,供日志追踪和审计回溯(如 “stepRiskCheck skipped: user.level=普通”)
与向导 UI 层联动反馈依赖状态
前端向导控件(如步骤条、导航按钮)不应只显示“已完成/未开始”,而应反映真实依赖就绪状态。后端可暴露一个轻量端点 /wizard/steps/status,返回每个步骤的:status(READY / BLOCKED / SKIPPED / EXECUTING)、blockedBy(字符串列表)、estimatedWait(毫秒,基于历史平均耗时估算)。
- 前端据此禁用尚未 READY 的下一步按钮,并悬停显示阻塞原因
- 对 BLOCKED 步骤,可主动轮询其依赖项状态变化,实现“依赖就绪即自动激活”体验

















