此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Integration 6.3.1Spring中文文档

此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Integration 6.3.1Spring中文文档

IntegrationFlow并且它的所有依赖组件都可以在运行时注册。 在 5.0 版本之前,我们使用了钩子。 从 Spring Framework 开始,我们使用 hook 进行编程注册。 下面的示例演示如何以编程方式注册 Bean:BeanFactory.registerSingleton()5.0instanceSupplierBeanDefinitionSpring中文文档

BeanDefinition beanDefinition =
         BeanDefinitionBuilder.genericBeanDefinition((Class<Object>) bean.getClass(), () -> bean)
               .getRawBeanDefinition();

((BeanDefinitionRegistry) this.beanFactory).registerBeanDefinition(beanName, beanDefinition);

请注意,在前面的示例中,hook 是方法的最后一个参数,在本例中由 lambda 提供。instanceSuppliergenericBeanDefinitionSpring中文文档

所有必要的 Bean 初始化和生命周期都是自动完成的,就像使用标准上下文配置 Bean 定义一样。Spring中文文档

为了简化开发体验,Spring Integration 引入了在运行时注册和管理实例的功能,如以下示例所示:IntegrationFlowContextIntegrationFlowSpring中文文档

@Autowired
private AbstractServerConnectionFactory server1;

@Autowired
private IntegrationFlowContext flowContext;

...

@Test
public void testTcpGateways() {
    TestingUtilities.waitListening(this.server1, null);

    IntegrationFlow flow = f -> f
            .handle(Tcp.outboundGateway(Tcp.netClient("localhost", this.server1.getPort())
                    .serializer(TcpCodecs.crlf())
                    .deserializer(TcpCodecs.lengthHeader1())
                    .id("client1"))
                .remoteTimeout(m -> 5000))
            .transform(Transformers.objectToString());

    IntegrationFlowRegistration theFlow = this.flowContext.registration(flow).register();
    assertThat(theFlow.getMessagingTemplate().convertSendAndReceive("foo", String.class), equalTo("FOO"));
}

当我们有多个配置选项并且必须创建多个类似流的实例时,这很有用。 为此,我们可以迭代我们的选项,并在循环中创建和注册实例。 另一种变体是当我们的数据源不是基于 Spring 的时,因此我们必须即时创建它。 这样的示例是 Reactive Streams 事件源,如以下示例所示:IntegrationFlowSpring中文文档

Flux<Message<?>> messageFlux =
    Flux.just("1,2,3,4")
        .map(v -> v.split(","))
        .flatMapIterable(Arrays::asList)
        .map(Integer::parseInt)
        .map(GenericMessage<Integer>::new);

QueueChannel resultChannel = new QueueChannel();

IntegrationFlow integrationFlow =
    IntegrationFlow.from(messageFlux)
        .<Integer, Integer>transform(p -> p * 2)
        .channel(resultChannel)
        .get();

this.integrationFlowContext.registration(integrationFlow)
            .register();

(由于 )可用于指定要注册的 Bean 名称,以控制其 ,并注册非 Spring Integration bean。 通常,这些附加的 Bean 是连接工厂(AMQP、JMS、(S)FTP、TCP/UDP 等)、序列化程序和反序列化程序,或任何其他必需的支持组件。IntegrationFlowRegistrationBuilderIntegrationFlowContext.registration()IntegrationFlowautoStartupSpring中文文档

当您不再需要动态注册的 Bean 及其所有依赖 Bean 时,您可以使用回调来删除它们。 有关更多信息,请参见 IntegrationFlowContext JavadocIntegrationFlowRegistration.destroy()IntegrationFlowSpring中文文档

从 V5.0.6 开始,定义中所有生成的 Bean 名称都以流 ID 作为前缀。 建议始终指定显式流 ID。 否则,将在 中启动同步屏障,以生成 的 Bean 名称并注册其 Bean。 我们在这两个操作上进行同步,以避免在将相同的生成的 Bean 名称用于不同的实例时出现争用条件。IntegrationFlowIntegrationFlowContextIntegrationFlowIntegrationFlow
从 V5.0.6 开始,定义中所有生成的 Bean 名称都以流 ID 作为前缀。 建议始终指定显式流 ID。 否则,将在 中启动同步屏障,以生成 的 Bean 名称并注册其 Bean。 我们在这两个操作上进行同步,以避免在将相同的生成的 Bean 名称用于不同的实例时出现争用条件。IntegrationFlowIntegrationFlowContextIntegrationFlowIntegrationFlow

此外,从版本 5.0.6 开始,注册生成器 API 具有新方法:. 如果您希望声明同一流的多个实例,并避免在流中的组件具有相同的 ID 时发生 Bean 名称冲突,这将非常有用,如以下示例所示:useFlowIdAsPrefix()Spring中文文档

private void registerFlows() {
    IntegrationFlowRegistration flow1 =
              this.flowContext.registration(buildFlow(1234))
                    .id("tcp1")
                    .useFlowIdAsPrefix()
                    .register();

    IntegrationFlowRegistration flow2 =
              this.flowContext.registration(buildFlow(1235))
                    .id("tcp2")
                    .useFlowIdAsPrefix()
                    .register();
}

private IntegrationFlow buildFlow(int port) {
    return f -> f
            .handle(Tcp.outboundGateway(Tcp.netClient("localhost", port)
                    .serializer(TcpCodecs.crlf())
                    .deserializer(TcpCodecs.lengthHeader1())
                    .id("client"))
                .remoteTimeout(m -> 5000))
            .transform(Transformers.objectToString());
}

在这种情况下,可以使用名称为 的 Bean 来引用第一个流的消息处理程序。tcp1.client.handlerSpring中文文档

当您使用 .iduseFlowIdAsPrefix()
当您使用 .iduseFlowIdAsPrefix()