有时候，当我们需要为流程节点统一添加性能监控、执行日志、权限校验或者全局异常处理时，不需要在每个组件里写重复代码。利用拦截器（FlowInterceptor），我们可以为节点修筑起一层强大的“影子逻辑”。


### 1、为什么需要拦截器？

在复杂的业务流程中，我们经常需要处理一些与核心业务无关、但又必不可少的逻辑：

* 日志审计：记录谁在什么时候执行了哪个节点，耗时多久。
* 参数预处理：进入节点前，统一校验上下文中的必要变量。
* 通用容错：当节点执行失败时，统一记录错误码或触发重试机制。

通过拦截器，这些逻辑可以像“影子”一样附着在节点之上，实现业务逻辑与治理逻辑的彻底解耦。



### 2、核心 API：FlowInterceptor 机制

在 Solon-Flow 中，如果说 Node（节点）是身体，Link（连线）是经络，那么 FlowInterceptor（拦截器）就是“监控探头”和“外挂装甲”。

它通过 AOP（面向切面编程） 机制，让你在不修改业务代码的情况下，统一解决以下问题：

* 审计：谁执行了哪个节点？耗时多久？
* 安全：当前上下文环境是否允许进入该节点？
* 治理：统一的异常处理、全局流水号注入。


最新版的 FlowInterceptor 将“流程拦截”与“节点监听”合二为一，提供了三个维度的控制：




| 维度 | 对应方法 | 作用范围 | 典型场景 |
| -------- | -------- | -------- | -------- |
| AOP 拦截    | doFlowIntercept     | 全图/子图     | 整体耗时统计、事务开启、全局上下文准备。     |
| 进入钩子     | onNodeStart     | 每个节点执行前     | 权限校验、输入参数日志、分支阻断。     |
| 退出钩子     | onNodeEnd     | 每个节点执行后     | 输出参数审计、节点状态持久化。     |


### 3、实战演练：编写你的第一个拦截器

我们将通过一个“执行链路追踪器”来展示其强大的控制力。

第一步：编写拦截器类


```java
import org.noear.solon.annotation.Component;
import org.noear.solon.flow.FlowContext;
import org.noear.solon.flow.FlowException;
import org.noear.solon.flow.Node;
import org.noear.solon.flow.intercept.FlowInterceptor;
import org.noear.solon.flow.intercept.FlowInvocation;

@Component
public class TraceInterceptor implements FlowInterceptor {
    /**
     * AOP 拦截：包裹了整个 FlowEngine.eval() 的执行过程
     */
    @Override
    public void doFlowIntercept(FlowInvocation invocation) throws FlowException {
        // 1. 执行前逻辑
        long start = System.currentTimeMillis();

        // 2. 触发后续链条（包含其他拦截器和真正的节点执行）
        invocation.invoke();

        // 3. 执行后逻辑
        System.out.println("流程 [" + invocation.getGraph().getId() + "] 执行完毕，耗时：" + (System.currentTimeMillis() - start) + "ms");
    }

    /**
     * 节点进入监听：在每个节点 Task 执行前触发
     */
    @Override
    public void onNodeStart(FlowContext context, Node node) {
        // 通过 context 拿到交换器，实现运行时干预
        if ("sensitive_task".equals(node.getId())) {
            System.out.println("检测到敏感节点，检查权限...");
            // 如果校验失败，可以调用 context.exchanger().interrupt(true) 阻断当前分支
        }
    }
}
```


第二步：注册到引擎

拦截器支持 Rank 排序，数值越小优先级越高。


```java
@Configuration
public class FlowConfig {
    @Bean
    public void initEngine(FlowEngine engine, TraceInterceptor trace) {
        // 注册全局拦截器，排序号为 1
        engine.addInterceptor(trace, 1);
    }
}
```


### 4、关键点：运行时阻断逻辑

这是拦截器最强大的功能之一。根据 FlowEngine 的底层逻辑，你在 onNodeStart 中的操作可以直接影响执行引擎的行为：

* `context.stop()`：立即停止整个流程图。适用于发现致命错误或全局熔断。
* `context.interrupt()`：仅阻断当前这条线。如果此时有并行节点在运行，它们不会受影响。


### 5、常见问题 (FAQ)

Q：拦截器里抛出异常会怎样？ A：异常会沿着 FlowInvocation 链条向上抛出。除非你手动 try-catch，否则流程会因为异常而中断，这正是实现“校验失败即停机”的理想方式。

Q：拦截器是线程安全的吗？ A：拦截器本身是单例注册的，但 onNodeStart 等方法传入的是当前线程的 FlowContext 和 Node，因此它是线程隔离的，你可以安全地在方法内部处理业务数据。

### 6、学习小结

* 全局控制找 doFlowIntercept。
* 精细监控找 onNodeStart/End。
* 注册记得设置 Rank 权重。

后续，我们将挑战 Solon-Flow 的高阶排兵布阵——《并行、聚合与循环：复杂网关的底层逻辑》。看引擎如何通过内部栈结构处理复杂的循环遍历！
