Spring 发布订阅频道接缝的集成广播在窃听时不起作用

Spring Integration Broadcasts of publish-subscribe-channel seams not to work when wiretapping

我在 int:publish-subscribe-channel 上收到消息,但窃听此频道时只会呼叫其中一个订阅者(就像使用直接频道一样)。当我注释掉窃听时,它按预期工作。我正在使用 Spring Boot 2.0.0.RC1。也可以使用 Spring Boot 1.5.10.RELEASE.

进行复制

以下配置按预期工作:

起始码:

ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args);
PublishSubscribeChannel subscribeChannel = context.getBean("subscriber.channel", PublishSubscribeChannel.class);
subscribeChannel.send(MessageBuilder.withPayload("Test-String").build());
context.close();

配置:

<int:publish-subscribe-channel id="subscriber.channel" />

<int:logging-channel-adapter channel="subscriber.channel" level="WARN" />
<int:logging-channel-adapter channel="subscriber.channel" level="ERROR" />

输出:

2018-02-07 16:08:51.308  WARN 11944 --- [           main] o.s.integration.handler.LoggingHandler   : Test-String
2018-02-07 16:08:51.315 ERROR 11944 --- [           main] o.s.integration.handler.LoggingHandler   : Test-String

当使用通道拦截器时,通道不是发布订阅者通道而是直接通道:

起始码:

ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args);
PublishSubscribeChannel subscribeChannel = context.getBean("subscriber.channel", PublishSubscribeChannel.class);
subscribeChannel.send(MessageBuilder.withPayload("Test-String").build());
context.close();

配置

<int:publish-subscribe-channel id="subscriber.channel" />

<int:logging-channel-adapter channel="subscriber.channel" level="WARN" />
<int:logging-channel-adapter channel="subscriber.channel" level="ERROR" />

<int:channel id="subscriber.channel">
    <int:interceptors>
        <int:wire-tap channel="incomeLogger"/>
    </int:interceptors>
</int:channel>

<int:logging-channel-adapter id="incomeLogger" level="INFO" />

堆栈跟踪:

Exception in thread "main" 2018-02-07 16:14:42.824  INFO 11928 --- [       Thread-3] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@667a738: startup date [Wed Feb 07 16:14:41 CET 2018]; root of context hierarchy
org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'subscriber.channel' is expected to be of type 'org.springframework.integration.channel.PublishSubscribeChannel' but was actually of type 'org.springframework.integration.channel.DirectChannel'
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:384)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1091)
at com.example.demo.DemoApplication.main(DemoApplication.java:17)

当我将启动代码更改为:

ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args);
MessageChannel subscribeChannel = context.getBean("subscriber.channel", MessageChannel.class);
subscribeChannel.send(MessageBuilder.withPayload("Test-String").build());
context.close();

然后一个"Subscriber"会被调用,通道被拦截器跟踪:

2018-02-07 16:17:11.415  INFO 10040 --- [           main] o.s.integration.handler.LoggingHandler   : Test-String
2018-02-07 16:17:11.416  WARN 10040 --- [           main] o.s.integration.handler.LoggingHandler   : Test-String

更新:

同样有效的是以下配置

<int:publish-subscribe-channel id="subscriber.channel">
    <int:interceptors>
        <int:wire-tap channel="incomeLogger"/>
    </int:interceptors>
</int:publish-subscribe-channel>

<int:logging-channel-adapter id="incomeLogger" level="INFO" />
<int:logging-channel-adapter channel="subscriber.channel" level="WARN" />
<int:logging-channel-adapter channel="subscriber.channel" level="ERROR" />

输出:

2018-02-07 17:08:56.923  INFO 11300 --- [           main] o.s.integration.handler.LoggingHandler   : Test-String
2018-02-07 17:08:56.923  WARN 11300 --- [           main] o.s.integration.handler.LoggingHandler   : Test-String
2018-02-07 17:08:56.923 ERROR 11300 --- [           main] o.s.integration.handler.LoggingHandler   : Test-String

这是预期的还是错误?或者我错过了什么?提前致谢。

看看你有什么:

<int:publish-subscribe-channel id="subscriber.channel" />

<int:channel id="subscriber.channel">
    <int:interceptors>
        <int:wire-tap channel="incomeLogger"/>
    </int:interceptors>
</int:channel>

实际上你声明了两个bean,但是它们都具有相同的id。因此,只有定义顺序中的第二个获胜。但由于它是一个简单的 channel,您肯定会在运行时以 DirectChannel 结束,从而消除了出现该 publish-subscribe-channel 结果的任何可能性。

你应该明白,XML配置是经过解析的,最终的真实对象模型可能会有所不同。

因此,您错误地使用相同的 id.

覆盖了目标 bean

您的 <int:interceptors> <int:publish-subscribe-channel id="subscriber.channel"> 的最新代码是正确的。而且我相信最新的日志正是您希望看到的。