如需使用最新稳定版本,请使用 Spring Integration 7.0.4spring-doc.cadn.net.cn

DSL 基础

org.springframework.integration.dsl 包包含前面提到的 IntegrationFlowBuilder API 以及多个 IntegrationComponentSpec 实现,这些实现同时也是构建器,并提供用于配置具体端点的流畅 API。 IntegrationFlowBuilder 基础设施为基于消息的应用程序提供通用的 企业集成模式(EIP),例如通道、端点、轮询器和通道拦截器。spring-doc.cadn.net.cn

重要

IntegrationComponentSpec 是一个 FactoryBean 实现,因此其 getObject() 方法不得从 Bean 定义中调用。 IntegrationComponentSpec 实现必须保持原样以用于 Bean 定义,框架将管理其生命周期。 对于目标 IntegrationComponentSpec 类型(即 FactoryBean 值),Bean 定义应使用 Bean 方法参数注入,而不是 Bean 方法引用。spring-doc.cadn.net.cn

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

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

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

transform 方法接受一个 lambda 表达式作为端点参数,用于操作消息负载。 该方法的实际参数是一个 GenericTransformer<S, T> 实例。 因此,此处可以使用任何提供的转换器(ObjectToJsonTransformerFileToStringTransformer 等)。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<?> 作为第一个参数的重载方法之一。 例如,以下代码将无法正常工作:spring-doc.cadn.net.cn

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

由于 lambda 表达式未保留参数类型,且框架将尝试将负载强制转换为 Message<?>,这将在运行时以 ClassCastException 失败。spring-doc.cadn.net.cn

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

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

Java DSL 可以为流定义中内联定义的对象注册 Bean,也可以重用现有的注入的 Bean。 如果为内联对象和现有 Bean 定义定义了相同的 Bean 名称,将抛出 BeanDefinitionOverrideException,表明此类配置是错误的。 然而,当您处理 prototype Bean 时,集成流处理器无法检测到现有的 Bean 定义,因为每次从 BeanFactory 调用 prototype Bean 时,我们都会获得一个新实例。 因此,提供的实例会直接在 IntegrationFlow 中使用,而无需进行任何 Bean 注册,也不会对现有的 prototype Bean 定义进行任何可能的检查。 然而,如果该对象具有显式的 id,且该名称的 Bean 定义位于 prototype 作用域中,则会为此对象调用 BeanFactory.initializeBean()spring-doc.cadn.net.cn