如何在应用程序启动时创建队列和交换?

How to create queues and exchanges at application start?

我正在使用 RabbitMQ 和 Spring Boot,我想创建应用程序启动时声明的所有队列和交换。

我绑定了一个交换器和两个队列。我还有另一个不绑定任何交换的队列。

兑换声明是这样的:

@Bean
TopicExchange exchange() {
    return new TopicExchange(name, false, false);
}

队列:

@Bean
Queue queue1() {
    return new Queue(name, false);
}

@Bean
Binding bindingLogger(Queue queue1, TopicExchange exchange) {
    return BindingBuilder.bind(queue1).to(exchange).with("routingKey");
}

以及没有绑定的队列:

@Bean
Queue queue2() {
    return new Queue(name, false);
}

另外,我在 类 中使用了 @Component 标签。

我认为这没问题,因为如果我添加一个“虚拟”@RabbitListener,所有队列和交换都会创建。添加如下内容:

@Component
public class DummyListener {
    @RabbitListener(queues = {FAKE_QUEUE_NAME})
    public void dummyMethod(Message message, Channel channel) {
        // The code never will enter here because nobody are going to
        // insert data into the queue.
        // This method is only to create queues and exchange on init
    }
}

但我认为这是一个肮脏的解决方案,有必要创建一个永远不会被触发的侦听器和一个永远不会被使用的队列。

而且,正如我之前所说,队列和交换声明工作得很好,并且在项目启动时创建,如果实现了这个“虚拟监听器”。

那么,如何在启动应用程序时创建交换器和队列(如果不存在)?有没有更优雅的方式?

我读过 rabbitAdmin 但我认为这是在运行时创建一个新队列(实际上我不知道我是否必须在开始和运行时以不同的方式管理)

提前致谢。

那些 Declarable 会在连接打开时填充到 RabbitMQ 代理中。 从 @RabbitListener.

开始的侦听器容器确实会发生这种情况

所有硬逻辑都是从提到的 RabbitAdmin:

/**
 * If {@link #setAutoStartup(boolean) autoStartup} is set to true, registers a callback on the
 * {@link ConnectionFactory} to declare all exchanges and queues in the enclosing application context. If the
 * callback fails then it may cause other clients of the connection factory to fail, but since only exchanges,
 * queues and bindings are declared failure is not expected.
 *
 * @see InitializingBean#afterPropertiesSet()
 * @see #initialize()
 */
@Override
public void afterPropertiesSet() {

另一个连接点当然是 RabbitTemplate 当您将消息生成到交换中时。

如果你真的不打算做任何消费或生产,你可以考虑在你的服务中注入一个AmqpAdmin并在你需要的时候调用它的initialize()

/**
 * Declares all the exchanges, queues and bindings in the enclosing application context, if any. It should be safe
 * (but unnecessary) to call this method more than once.
 */
@Override // NOSONAR complexity
public void initialize() {

然而,从这里开始的问题是:如果您不打算在进一步的逻辑中使用它们,那么在您的应用程序中拥有所有这些声明有什么意义。看起来像是对 AMQP API 的担忧和滥用的混合体。最好在您的应用程序之外声明这些实体,例如使用 RabbitMQ 管理控制台或命令行工具...

您可以简单地打开连接。如果您使用 Spring 引导,请参阅

如果你没有使用Spring引导,添加一个实现SmartLifecycle@Bean并在start()中打开连接。