对于最新的稳定版本,请使用 Spring Integration 6.4.3spring-doc.cadn.net.cn

DSL 基础知识

org.springframework.integration.dslpackage 包含IntegrationFlowBuilderAPI 和一些IntegrationComponentSpec实现,它们也是构建器,并提供 Fluent API 来配置具体端点。 这IntegrationFlowBuilder基础设施为基于消息的应用程序(例如通道、终端节点、轮询程序和通道拦截器)提供常见的企业集成模式 (EIP)。spring-doc.cadn.net.cn

重要

IntegrationComponentSpec是一个FactoryBeanimplementation 的 Implementation 中实现,因此其getObject()method 不能从 bean 定义中调用。 这IntegrationComponentSpec对于 Bean 定义,实现必须保持原样,框架将管理其生命周期。 目标的 Bean 方法参数注入IntegrationComponentSpectype (aFactoryBean值)必须用于IntegrationFlowbean 定义,而不是 bean 方法引用。spring-doc.cadn.net.cn

端点在 DSL 中表示为动词,以提高可读性。 以下列表包括常见的 DSL 方法名称和关联的 EIP Endpoint:spring-doc.cadn.net.cn

从概念上讲,集成流程是通过将这些端点组合成一个或多个消息流来构建的。 请注意,EIP 并未正式定义术语“消息流”,但将其视为使用众所周知的消息传递模式的工作单元会很有用。 DSL 提供了一个IntegrationFlow组件来定义通道和它们之间的端点的组合,但现在IntegrationFlow仅扮演配置角色以在应用程序上下文中填充真实 bean,而不在运行时使用。 但是,用于IntegrationFlow可以作为Lifecycle控制start()stop()对于整个流,它被委托给与此关联的所有 Spring 集成组件IntegrationFlow. 以下示例使用IntegrationFlowFluent API 来定义IntegrationFlowbean 使用 EIP 方法IntegrationFlowBuilder:spring-doc.cadn.net.cn

@Bean
public IntegrationFlow integerFlow() {
    return IntegrationFlow.from("input")
            .<String, Integer>transform(Integer::parseInt)
            .get();
}

transform方法接受 Lambda 作为终端节点参数以对消息负载进行作。 此方法的真正参数是GenericTransformer<S, T>实例。 因此,任何提供的转换器 (ObjectToJsonTransformer,FileToStringTransformer和其他)都可以在此处使用。spring-doc.cadn.net.cn

在被窝里,IntegrationFlowBuilder识别MessageHandler及其端点,使用MessageTransformingHandlerConsumerEndpointFactoryBean分别。 考虑另一个例子:spring-doc.cadn.net.cn

@Bean
public IntegrationFlow myFlow() {
    return IntegrationFlow.from("input")
                .filter("World"::equals)
                .transform("Hello "::concat)
                .handle(System.out::println)
                .get();
}

前面的示例将Filter → Transformer → Service Activator. 流程是 “'单向'”。 也就是说,它不提供回复消息,而只将有效负载打印到 STDOUT。 终端节点使用直接通道自动连接在一起。spring-doc.cadn.net.cn

lambda 和Message<?>参数

在 EIP 方法中使用 lambda 表达式时,“input” 参数通常是消息负载。 如果您希望访问整个消息,请使用采用Class<?>作为第一个参数。 例如,this 将不起作用:spring-doc.cadn.net.cn

.<Message<?>, Foo>transform(m -> newFooFromMessage(m))

这将在运行时失败,并显示ClassCastException因为 Lambda 不保留参数类型,并且框架会尝试将有效负载转换为Message<?>.spring-doc.cadn.net.cn

相反,请使用:spring-doc.cadn.net.cn

.(Message.class, m -> newFooFromMessage(m))
Bean 定义覆盖

Java DSL 可以为流定义中内联定义的对象注册 bean,也可以重用现有的注入的 bean。 如果为内嵌对象和现有 bean 定义定义了相同的 bean 名称,则BeanDefinitionOverrideException表示此类配置错误。 但是,当您处理prototypebean 中,无法从集成流处理器中检测现有的 bean 定义,因为每次我们调用prototypebean 的BeanFactory我们得到一个新实例。 这样,在IntegrationFlow原样没有任何 bean 注册和对现有prototypebean 定义。 然而BeanFactory.initializeBean()如果此对象具有显式的id并且此名称的 bean 定义位于prototype范围。spring-doc.cadn.net.cn