在不阻塞主线程的情况下启动 JMSListener
Start a JMSListener without block the main thread
我正在尝试通过 spring 引导启动一个应用程序,该应用程序具有 JMSListener 以连接到外部 ActiveMQ,即使 ActiveMQ 已关闭,此应用程序也需要启动。
我在连接中使用了故障转移传输协议,但是当我启动应用程序时主线程被阻塞,而 JMS 尝试建立连接并且应用程序在建立第一个连接之前不会启动。
我正在尝试这个解决方案,我在其中扩展 DefaultMessageListenerContainer 并在将释放主线程的新线程中将 start 方法覆盖到 运行。
Consumer.java
@SpringBootApplication
public class Consumer {
public static void main(String[] args) {
SpringApplication.run(Consumer.class, args);
System.out.println("Consumer Start");
}
}
接收器
@Component
public class Receiver {
@Bean
public JmsListenerContainerFactory<?> myFactory(ConnectionFactory connectionFactory,
DefaultJmsListenerContainerFactoryConfigurer configurer) {
DefaultJmsListenerContainerFactory factory = new MyListenerContainerFactory();
configurer.configure(factory, connectionFactory);
return factory;
}
@JmsListener(destination = "mailbox", containerFactory = "myFactory")
public void receiveMessage(String email) {
System.out.println("Received <" + email + ">");
}
}
MyListenerContainer.java
public class MyListenerContainer extends DefaultMessageListenerContainer {
@Override
public void start() throws JmsException {
new Thread(() -> {
super.start();
}).start();
}
}
MyListenerContainerFactory.java
public class MyListenerContainerFactory extends DefaultJmsListenerContainerFactory {
@Override
protected DefaultMessageListenerContainer createContainerInstance() {
return new MyListenerContainer();
}
}
1º问题:
这个解决方案有效,但我不确定这是否不会破坏 spring bean 的开始,因为我在创建连接之前完成了 start 方法。这会破坏 spring 引导中的 bean 创建过程吗?
2º问题:
除此之外,如果我在同一个应用程序中有一个 JMSListener 和一个 JMSProducer,它们会尝试使用相同的连接还是使用不同的连接?
如果有人有更好的不同解决方案,请分享。
感谢您抽出宝贵时间并致以最诚挚的问候
贝尔纳多·内维斯
- 使用
factory.setAutoStartup(false);
可能更干净,这将阻止 Spring 尝试启动容器;准备好后使用 container.start()
(在任何你想要的线程上)。
@Autowired
private JmsListenerEndpointRegistry registry;
...
registry.start(); // starts all containers
// or
registry.getListenerContainer(myContainerId).start();
- 他们将使用相同的连接。
我正在尝试通过 spring 引导启动一个应用程序,该应用程序具有 JMSListener 以连接到外部 ActiveMQ,即使 ActiveMQ 已关闭,此应用程序也需要启动。
我在连接中使用了故障转移传输协议,但是当我启动应用程序时主线程被阻塞,而 JMS 尝试建立连接并且应用程序在建立第一个连接之前不会启动。
我正在尝试这个解决方案,我在其中扩展 DefaultMessageListenerContainer 并在将释放主线程的新线程中将 start 方法覆盖到 运行。
Consumer.java
@SpringBootApplication
public class Consumer {
public static void main(String[] args) {
SpringApplication.run(Consumer.class, args);
System.out.println("Consumer Start");
}
}
接收器
@Component
public class Receiver {
@Bean
public JmsListenerContainerFactory<?> myFactory(ConnectionFactory connectionFactory,
DefaultJmsListenerContainerFactoryConfigurer configurer) {
DefaultJmsListenerContainerFactory factory = new MyListenerContainerFactory();
configurer.configure(factory, connectionFactory);
return factory;
}
@JmsListener(destination = "mailbox", containerFactory = "myFactory")
public void receiveMessage(String email) {
System.out.println("Received <" + email + ">");
}
}
MyListenerContainer.java
public class MyListenerContainer extends DefaultMessageListenerContainer {
@Override
public void start() throws JmsException {
new Thread(() -> {
super.start();
}).start();
}
}
MyListenerContainerFactory.java
public class MyListenerContainerFactory extends DefaultJmsListenerContainerFactory {
@Override
protected DefaultMessageListenerContainer createContainerInstance() {
return new MyListenerContainer();
}
}
1º问题: 这个解决方案有效,但我不确定这是否不会破坏 spring bean 的开始,因为我在创建连接之前完成了 start 方法。这会破坏 spring 引导中的 bean 创建过程吗?
2º问题: 除此之外,如果我在同一个应用程序中有一个 JMSListener 和一个 JMSProducer,它们会尝试使用相同的连接还是使用不同的连接?
如果有人有更好的不同解决方案,请分享。
感谢您抽出宝贵时间并致以最诚挚的问候
贝尔纳多·内维斯
- 使用
factory.setAutoStartup(false);
可能更干净,这将阻止 Spring 尝试启动容器;准备好后使用container.start()
(在任何你想要的线程上)。
@Autowired
private JmsListenerEndpointRegistry registry;
...
registry.start(); // starts all containers
// or
registry.getListenerContainer(myContainerId).start();
- 他们将使用相同的连接。