Skip to content

Spring 集成 0.2.2+

拓展后的 SpringReflectiveGraphCompiler 允许你利用 Spring 容器来管理节点和边的具体实现。

核心机制

当编译器扫描 @GraphComposer 类时,对于被标记为图组件 (@GraphNode, @ConditionalEdge@GraphCompileConfig) 且值为 null 的字段,编译器会尝试从 Spring 的 ApplicationContext 中查找匹配的 Bean 并自动填充。

仅限图组件

对于普通的业务依赖(如 UserService),请继续使用 Spring 标准的构造函数注入或 @Autowired

使用示例

假设你有一个复杂的业务逻辑节点,被定义为一个独立的 Spring Bean:

1. 定义节点 Bean

java
@Component("orderValidator") // Bean 名称
public class OrderValidatorNode implements AsyncNodeAction {
    
    @Autowired
    private OrderService orderService; // 节点内部依然可以使用标准的 Spring 注入

    @Override
    public CompletableFuture<Map<String, Object>> execute(State state) {
        // ... 复杂的校验逻辑 ...
        return CompletableFuture.completedFuture(result);
    }
}

2. 在图中引用该 Bean

在你的 GraphComposer 中,你不需要手动 new 这个节点,只需要声明字段并加上注解:

java
@GraphComposer
public class OrderWorkflow {

    // 引用 Spring 容器中现有的 Bean
    // 编译器会自动找到名为 "orderValidator" 的 Bean 并注入
    @GraphNode(id = "orderValidator", next = "payment")
    private AsyncNodeAction orderValidator; 
    
    // 依然支持内联定义的简单节点
    @GraphNode(id = "payment", isStart = false)
    @Qualifier("paymentNode") // 可以使用 @Qualifier 指定候选
    final AsyncNodeAction payment = state -> {
        System.out.println("Processing payment...");
        return CompletableFuture.completedFuture(Collections.emptyMap());
    };
}

解析规则

  1. 第一级:候选名称匹配

    • 条件:调用方提供了候选名称(candidateName),且不为空。
    • 逻辑:检查容器中是否存在名为 candidateName 的 Bean,且该 Bean 的类型与字段类型兼容。
  2. 第二级:字段名称匹配

    • 条件:字段名与候选名称不同(或者没有候选名称)。
    • 逻辑:检查容器中是否存在与 Java 字段名 同名的 Bean,且该 Bean 的类型与字段类型兼容。
  3. 第三级:Spring 标准依赖解析

    • 条件:前两级基于名称的直接匹配均未能找到合适的 Bean。
    • 逻辑:将当前字段封装为 DependencyDescriptor,调用 Spring 的 resolveDependency 机制进行依赖解析。支持包括但不限于按类型匹配、@Primary 优先级判定、@Qualifier 限定符解析以及泛型/集合类型的注入。

关于 candidateName

目前只有 @GraphNode 注解的 id 属性会被用作 candidateName

找不到唯一匹配的情况

如果根据上述规则找不到唯一的匹配,Composer 将无法正确通过编译,抛出 GraphDefinitionException 异常。

Released under the Apache 2.0 License.