一、前言

    当启动程序时,并且MQ队列中有消息,这些消息的消费就会在应用程序完全启动之前开始,但是启动程序要初始化一些程序要用的数据,在没有初始化完成时消费这些消息会报错,所以希望在程序初始化完成后,再启动RabbitMQ的监听容器。

二、解决方案

    @RabbitListener注解的属性中有两个属性,一个是id,给监听容器一个id标识;一个是autoStartup,当autoStartup为false的时候,监听容器就不会自动启动,然后我们可以通过使用单个容器的ID,调用RabbitListenerEndpointRegistry类的getListenerContainer(String id)方法来获得对单个容器的引用,并执行strat方法,启动容器。

具体代码:

1、修改容器为不自动启动

    @RabbitListener(id = "xue",queues = "xue.xiao.bai",autoStartup = "false")
    @RabbitHandler
    public void process(String command){
        System.out.println("从xue.xiao.bai队列得到消息为:"+command+"\n");
    }

2、程序初始化数据完毕后,再启动容器

@Component
public class MyApplicationRunner implements ApplicationRunner {

    private final RabbitListenerEndpointRegistry registry;

    @Autowired
    public MyApplicationRunner(RabbitListenerEndpointRegistry registry) {
       this.registry =  registry;
    }

    @Override
    public void run(ApplicationArguments args) {
        //执行一些数据初始化代码(省略)
        //得到容器的对象
        MessageListenerContainer container = registry.getListenerContainer("xue");
        //判断容器状态
        if(!container.isRunning()){
            //开启容器
            container.start();
            System.out.println("开启容器");
        }
    }
}

三、扩展

    RabbitListenerEndpointRegistry类,容器是用一个map来管理的

private final Map<String, MessageListenerContainer> listenerContainers = new ConcurrentHashMap();
根据容器id得到对应的容器对象
public MessageListenerContainer getListenerContainer(String id)
得到容器id的set集合
public Set<String> getListenerContainerIds()
得到监听容器的集合
public Collection<MessageListenerContainer> getListenerContainers()

 

    AbstractMessageListenerContainer类实现了MessageListenerContainer类

    AbstractMessageListenerContainer类中的start()方法:启动对消息队列的监听。

public void start()

    AbstractMessageListenerContainer类中的start()方法:启动对消息队列的监听。

public void stop()

~~OVER~~

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐