如何使用DefaultMessageListenerContainer(在spring-boot中)拥有动态选择器?

时间:2016-08-15 11:39:29

标签: spring spring-boot activemq

我有一个带有ActiveMQ JMS的spring-boot应用程序。我在应用程序中有一个队列,它将获得带有字符串属性的消息。颜色值可以是红色,绿色或蓝色。应用程序有一个Rest服务,它将获取颜色列表{一个或多个},在侦听队列中的消息时应将其用作SELECTOR。在应用程序的生命周期中,这可能会改变,因此SELECTOR的值可能看起来像 “color ='red'”“color ='blue'OR color ='red'”“color ='green'”

@Bean
MessageListenerAdapter adapter() {        
    return new MessageListenerAdapter(new Object() {
        // message handler
    });
}
@Bean
DefaultMessageListenerContainer container(ConnectionFactory cf) throws Exception {
    DefaultMessageListenerContainer c = new DefaultMessageListenerContainer();
    c.setMessageListener(adapter());
    c.setConcurrency(this.concurrency);
    c.setMessageSelector(this.selector);
    c.setConnectionFactory(cf);
    c.setDestinationName(this.q);

    return c;
}

计划使用上面的代码来实现这一目标;代码可以正常启动初始选择器,但是当选择器需要更改后面的代码不起作用。

c.stop();
// modify value of selector
c.setMessageSelector(this.selector);
c.start();

看起来,我有一个有效的解决方案。我将 @Scope(“prototype”)放在方法容器()的顶部,并有一个方法,只要选择器发生变化,就会实例化一个新的DefaultMessageListenerContainer。

public void xx(String selector) {
    this.selector = selector;
    DefaultMessageListenerContainer c = 
        context.getBean("container", DefaultMessageListenerContainer.class);
    c.start();
}

这是正确的方法吗?此外,当选择器更改并且我实例化一个新的DefaultMessageListenerContainer时,关闭/停止现有DefaultMessageListenerContainer的正确方法是什么?

的问候, 瑜珈

1 个答案:

答案 0 :(得分:1)

原型对我来说是个坏主意。

MessageListenerContainer是一个负责处理特定队列或主题配置的侦听器的单例。选择器是JMS规范,因此您基本上需要在运行时重新配置侦听器容器,这将要求您完全停止侦听器,更改其配置并重新启动它。我没有看到你的代码,但我没有看到它不起作用的原因。

话虽如此,为什么要使用选择器呢?如果选择器在应用程序的生命周期内发生变化,那么在您自己的逻辑中实际执行该选择不是更好吗?如果在同一队列中有多个消息类型并且您需要不同的线程池(例如,您希望5个并发侦听器用于“红色”,而只有2个用于绿色),则在JMS级别拥有一个选择器很有趣。如果你没有那个具有过滤传入消息的通用路由的要求可能是一个更好的主意。

如果您确实有这个要求,停止容器,更改其配置并重新启动它应该有效。不幸的是,我没有创建SPR-14604来跟踪此问题。

相关问题