Skip to content

生命周期钩子

除了静态的注解定义外,SAA Graph Composer 提供了 GraphBuildLifecycle 接口,允许你在图被最终编译成 CompiledGraph 之前,直接介入并修改底层的 StateGraph 构建器。

这为开发者提供了极大的灵活性,不仅可以解决注解无法表达的复杂连线问题,还能实现动态构建、结构校验等高级需求。

接口定义

实现该接口的 @GraphComposer 类将获得介入图构建流程的能力。框架提供了两个关键的生命周期钩子,允许在自动化编排的不同阶段注入自定义逻辑。

java
public interface GraphBuildLifecycle {
    /**
     * 在所有的键注册完成后触发,即 new StateGraph() 之后,但在任何节点或连线添加之前。
     * 
     * @param builder 底层图构建器
     * @throws GraphStateException 如果构建逻辑有误
     */
    default void afterKeyRegistration(StateGraph builder) throws GraphStateException {}

    /**
     * 在编译前触发,暴露底层的 StateGraph 构建器。
     * 你可以在此方法中补充节点、添加连线或进行校验。
     *
     * @param builder 底层图构建器
     * @throws GraphStateException 如果构建逻辑有误
     */
    default void beforeCompile(StateGraph builder) throws GraphStateException {}
}

混合构建

这是最常见的使用场景。

当节点逻辑适合用 Spring Bean 管理(使用 @GraphNode),但连线逻辑过于复杂(例如动态条件、依赖配置)而不便在 @GraphNodenext 属性中硬编码时,可以采用“注解定义节点 + 代码定义连线”的混合模式。

示例代码

java
@GraphComposer
public class HybridGraphComposer implements GraphBuildLifecycle {

    private static final Logger log = LoggerFactory.getLogger(HybridGraphComposer.class);

    public static final String NODE_A = "nodeA";

    // 1. 使用注解定义节点,但故意省略 next 和 isStart 属性
    // 框架会自动注册此节点,但暂时不建立任何连接
    @GraphNode(id = NODE_A)
    final AsyncNodeActionWithConfig actionA = (state, config) -> {
        String input = (String) state.value("input").orElse("");
        return CompletableFuture.completedFuture(Map.of("result", input + "-processed"));
    };

    @Override
    public void beforeCompile(StateGraph builder) throws GraphStateException {
        // 2. 在钩子中手动补充连线逻辑
        // 逻辑:Start -> NodeA -> End
        builder.addEdge(StateGraph.START, NODE_A);
        builder.addEdge(NODE_A, StateGraph.END);

        log.info(String.valueOf(builder.getGraph(GraphRepresentation.Type.MERMAID)));
    }

}

💡 图构建 API

关于 addNode, addEdge, addConditionalEdge 等方法的详细参数说明和更多高级用法,请参阅 Spring AI Alibaba 官方文档

动态修剪与扩展

利用 beforeCompile,你可以根据环境变量、配置中心的配置或 License 授权情况,动态地调整图结构。

示例:根据配置开启审计节点

java

@Value("${app.audit.enabled:false}")
private boolean auditEnabled;

@Override
public void beforeCompile(StateGraph builder) throws GraphStateException {

    if (auditEnabled) {
        // If auditing is enabled, add the audit node between process and end
        builder.addNode(NODE_AUDIT, AsyncNodeAction.node_async(nodeAudit));
        builder.addEdge(NODE_PROCESS, NODE_AUDIT);
        builder.addEdge(NODE_AUDIT, StateGraph.END);
    } else {
        // Directly connect process node to end
        builder.addEdge(NODE_PROCESS, StateGraph.END);
    }

    log.info(String.valueOf(builder.getGraph(GraphRepresentation.Type.MERMAID)));
}

Released under the Apache 2.0 License.