Spring integration 在动态(手动)流注册期间,从未为子流调用Lifecycle start()

Spring integration 在动态(手动)流注册期间,从未为子流调用Lifecycle start(),spring-integration,Spring Integration,我正在使用IntegrationFlow的动态(手动)注册(通过IntegrationFlowContext),我的集成流由一个发布/订阅通道组成,其中一个订阅服务器是子流。事实证明,子流组件从未启动,因为子流(作为主流的集成组件)未添加到StandardIntegrationFlow构造函数中的“生命周期”列表中,该构造函数仅检查AbstractEndpoint和EndpointSpec实例: @SuppressWarnings("unchecked") StandardIntegra

我正在使用IntegrationFlow的动态(手动)注册(通过IntegrationFlowContext),我的集成流由一个发布/订阅通道组成,其中一个订阅服务器是子流。事实证明,子流组件从未启动,因为子流(作为主流的集成组件)未添加到StandardIntegrationFlow构造函数中的“生命周期”列表中,该构造函数仅检查AbstractEndpoint和EndpointSpec实例:

    @SuppressWarnings("unchecked")
StandardIntegrationFlow(Set<Object> integrationComponents) {
    this.integrationComponents = new LinkedHashSet<Object>(integrationComponents);
    for (Object integrationComponent : integrationComponents) {
        if (integrationComponent instanceof AbstractEndpoint) {
            this.lifecycles.add((Lifecycle) integrationComponent);
        }
        else if (integrationComponent instanceof EndpointSpec) {
            BeanNameAware endpoint = ((EndpointSpec<?, BeanNameAware, ?>) integrationComponent).get().getT1();
            this.lifecycles.add((Lifecycle) endpoint);
        }
    }
}
@SuppressWarnings(“未选中”)
标准集成流(设置集成组件){
this.integrationComponents=新的LinkedHashSet(integrationComponents);
用于(对象集成组件:集成组件){
if(抽象端点的integrationComponent实例){
this.lifecycles.add((生命周期)integrationComponent);
}
else if(EndpointSpec的集成组件实例){
BeanNameware端点=((EndpointSpec)integrationComponent.get().getT1();
this.lifecycles.add((生命周期)端点);
}
}
}
调用StandardIntegrationFlow start()方法时,将启动主流的所有组件,但不会启动子流的所有组件。随后,EventDrivenConsumer的start()方法不会被调用,MessageHandler(在我的例子中)也不会被订阅到发布/订阅通道

我相信问题在于上面的代码

下面是一个测试用例,它演示了这种行为(相对于静态定义流的行为):

@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@肮脏的环境
公共类子流测试{
@自动连线
公共集成FlowContext集成FlowContext;
@自动连线
公共集成流;静态流;
@自动连线
私有可轮询信道结果;
@试验
公共void testStaticFlow(){
integrationFlowContext.messagingTemplateFor(“静态流”).send(新的GenericMessage(“测试”));
Message receive=this.result.receive(1000);
assertNotNull(接收);
assertEquals(“test”,receive.getPayload());
}
@试验
public void testDynamicFlow(){
register(“dynamicFlow”,flow->flow
.PublishSubscribeBchannel(p->p.subscribe(f->f.handle)(新的BridgeHandler())
。频道(结果);
integrationFlowContext.messagingTemplateFor(“dynamicFlow”).send(新的GenericMessage(“test”));
Message receive=this.result.receive(1000);
assertNotNull(接收);
assertEquals(“test”,receive.getPayload());
}
@配置
@使能集成
公共静态类上下文配置{
@豆子
公共集成流staticFlow(){
回流->流量
.PublishSubscribeBchannel(p->p.subscribe(f->f.handle)(新的BridgeHandler())
.channel(result());
}
@豆子
公共可轮询频道结果(){
return MessageChannels.queue().get();
}
}
}
看起来这是一个bug:

考虑在我们找到解决方案之前不要使用子流

这项新功能确实存在一些缺陷。

看起来这是一个缺陷:

考虑在我们找到解决方案之前不要使用子流


这项新功能确实存在一些缺陷。

谢谢。目前,作为一种解决方法,在动态上下文注册之后,我立即从上下文中获取EventDrivenConsumer类型的bean,并手动调用它们的start()(因为在我的案例中,这些是我需要启动的惟一bean)。您好,我再次使用spring integration java dsl:1.2.0.BUILD-SNAPSHOT,这是修复的,但我注意到另一个问题(与生命周期相关)问题:当通过IntegrationFlowContext.remove()删除流时,lifecycle.stop()不会在删除的流上调用,我认为应该调用lifecycle.stop()(在删除流之后,我遇到了轮询器等挂起的组件)。我认为这是一个好问题:!作为一种解决方法,您应该
stop()
在调用
destroy()
之前手动流动。谢谢。目前作为一种解决方法,在动态上下文注册之后,我正在从上下文中获取EventDrivenConsumer类型的bean,并手动对其调用start()(因为在我的案例中,这些是我需要启动的唯一bean).Hi再次说明,我使用的是spring integration java dsl:1.2.0.BUILD-SNAPSHOT,这是修复的,但是我注意到另一个(与生命周期相关的)问题:当通过IntegrationFlowContext.remove()删除流时,我认为应该在删除的流上调用lifecycle.stop()(在删除流之后,我遇到了轮询器等挂起的组件)。我认为这是一个好问题:!作为一种解决方法,在调用
destroy()
之前,您应该手动
stop()
流。
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@DirtiesContext
public class SubflowTests {

@Autowired
public IntegrationFlowContext integrationFlowContext;

@Autowired
public IntegrationFlow staticFlow;

@Autowired
private PollableChannel result;

@Test
public void testStaticFlow() {
    integrationFlowContext.messagingTemplateFor("staticFlow").send(new GenericMessage<String>("test"));

    Message<?> receive = this.result.receive(1000);
    assertNotNull(receive);
    assertEquals("test", receive.getPayload());
}

@Test
public void testDynamicFlow() {
    integrationFlowContext.register("dynamicFlow", flow -> flow
            .publishSubscribeChannel(p -> p.subscribe(f -> f.handle(new BridgeHandler())
                    .channel(result))));

    integrationFlowContext.messagingTemplateFor("dynamicFlow").send(new GenericMessage<String>("test"));

    Message<?> receive = this.result.receive(1000);
    assertNotNull(receive);
    assertEquals("test", receive.getPayload());

}

@Configuration
@EnableIntegration
public static class ContextConfiguration {

    @Bean
    public IntegrationFlow staticFlow() {
        return flow -> flow
                .publishSubscribeChannel(p -> p.subscribe(f -> f.handle(new BridgeHandler())
                        .channel(result())));
    }

    @Bean
    public PollableChannel result() {
        return MessageChannels.queue().get();
    }
}
}