该版本仍在开发中,尚未被视为稳定。对于最新的稳定版本,请使用 Spring Integration 7.0.0spring-doc.cadn.net.cn

动态集成流与运行时集成流程

集成流程并且其所有依赖组件都可以在运行时被注册。在5.0版本之前,我们使用BeanFactory.registerSingleton()钩。 从春季框架开始5.0,我们使用实例提供商程序化钩子豆子定义注册。 以下示例展示了如何编程注册豆子:spring-doc.cadn.net.cn

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

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

注意,在前面的例子中,实例提供商钩子是genericBean定义此时由 lambda 提供。spring-doc.cadn.net.cn

所有必要的豆初始化和生命周期都是自动完成的,就像标准上下文配置豆定义一样。spring-doc.cadn.net.cn

为了简化开发体验,推出了 Spring 集成集成流上下文注册和管理集成流程运行时实例,如下示例所示:spring-doc.cadn.net.cn

@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事件源,如下示例所示:spring-doc.cadn.net.cn

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();

集成流程注册构建器(由于IntegrationFlowContext.registration())可用于指定集成流程登记,控制其自动启动注册时,则是非Spring集成的豆子。通常,这些额外的豆子是连接工厂(AMQP、JMS、(S)FTP、TCP/UDP等)、串行器和解串器,或其他所需的支持组件。spring-doc.cadn.net.cn

你可以使用IntegrationFlowRegistration.destroy()回调以移除动态注册集成流程以及当你不再需要它们时,所有依赖它们的豆子。参见集成流上下文Javadoc更多信息请见。spring-doc.cadn.net.cn

从5.0.6版本开始,所有生成的豆子名称都在集成流程定义前加了流ID作为前缀。我们建议始终指定显式的流ID。否则,同步障碍将在集成流上下文,生成豆名集成流程并注册其豆子。我们对这两种作进行同步,以避免在生成的豆子名称被用于不同时出现竞争条件集成流程实例。

此外,从5.0.6版本开始,注册构建API新增了一种方法:useFlowIdAsPrefix(). 如果你想声明同一流程的多个实例,并且当流程中组件具有相同 ID 时避免豆名冲突,这非常有用,如下示例所示:spring-doc.cadn.net.cn

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 a 的名称引用TCP1.client.handler.spring-doc.cadn.net.cn

身份证属性是你使用E时必需的useFlowIdAsPrefix().