在 Spring 启动时即时修改 @JMSListener 目标

Modify @JMSListener destination on-the-fly on Spring Boot

我开发了一个 @JMSListener,它从 Java 属性获取目的地并且工作正常。

但现在我需要能够在运行时更改队列的 "destination" 而不必重置整个应用程序,即使我在运行时修改属性,队列 "destination" 不变。

这是我们实现@JMSListener 的方式:


import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.support.converter.MessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

@Component("b2b.CCRReceiver")
@Slf4j
public class CCRReceiver {

  //SOME_VARIABLES

    @Transactional
    @JmsListener(destination = "${tibco.configuration.queues.upsert}", containerFactory = "jmsFactory", concurrency = "${jms.concurrency}")
    public void receiveMessage(Message message) {
        //DO_SOME_STUFF
    }
}

如您所见,我第一次从值表达式中获取目标并且工作正常,但后来我不知道如何访问 JMSListener 并更改它的目标。

这能做到吗?有什么办法可以改变目的地吗?

或者我必须以允许我这样做的其他方式实现此 JMS 侦听器?

这应该有效:

  • 给听众一个id属性

  • 自动连接 JmsListenerEndpointRegistry(或以其他方式获取对它的引用)

  • registry.getListenerContainer("myListener").stop();

  • registry.getListenerContainer("myListener").shutdown();

  • ((AbstractMessageListenerContainer) registry.getListenerContainer("myListener")) .setDestinationName("newOne")

  • registry.getListenerContainer("myListener").initialize();

  • registry.getListenerContainer("myListener").start();

我使用组件侦听器线程解决了这个问题。使用TaskExecutor和ApplicationContext来管理。您可以在运行时创建。我还在努力。我也会尝试 Gary Russell 的建议。 对不起英语。欢迎指正。

applicationContext.getBean(ExampleListenerJMS.class);
... 
taskExecutor.execute(exampleListenerJMS);

class 侦听器“实现 Runnable,MessageListener”,实现了自定义连接管理器(不同的 activemq 服务器)。

@Component
@Scope("application")
public class ExampleListenerJMS implements Runnable, MessageListener {

private EspecificManagerJMS jms = new EspecificManagerJMS();

@Override
public void run() {
    customAndChekingActions();
}

protected void customAndChekingActions() {
...
    try {
        Destination destination = jms.getSession().createQueue(queue);
        MessageConsumer consumer = jms.getSession().createConsumer(destination);
        consumer.setMessageListener(this);
        ...
    } catch (JMSException e) {
        e.printStackTrace();
        ...
    }
}

@Override
public void onMessage(Message message) {
...
}

希望对你有所帮助