当兔子最初失败时豆类未能启动

时间:2015-05-08 17:59:03

标签: java amqp spring-amqp

org.springframework.web.context.ContextLoader | localhost-startStop-1 |     Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'simpleListenerContainer' defined
 in class path resource [com/company/product/api/config/amqp/InternalAmqpConfiguration.class]: Bean instantiation v
ia factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate

如果在我的Spring MVC应用程序启动之前Rabbit已关闭,那么依赖于CachingConnectionFactory的许多bean都无法初始化。如下所示:

 @Autowired
@Bean
public SimpleRabbitListenerContainerFactory simpleistenerContainer(
    @Qualifier("internal") CachingConnectionFactory connectionFactory,
    RabbitAdmin admin) {

    for(Listeners listener : Listeners.values()) {
        Queue q = new Queue(listener.queue, true, true, true);
        admin.declareQueue(q);
        admin.declareBinding(
            BindingBuilder.bind(q)
                .to(new TopicExchange(listener.exchange, true, false))
                .with((listener.appendWildcard) ? listener.routingKey + ""
                    + ".*" : listener.routingKey)
        );
    }

    SimpleRabbitListenerContainerFactory listenerContainerFactory = new
        SimpleRabbitListenerContainerFactory();

    listenerContainerFactory.setConnectionFactory(connectionFactory);

    return listenerContainerFactory;
}

由于缺少其中一个依赖项而未初始化bean,因此失败并且无法恢复。我考虑在ConnectionListener上使用CachingConnectionFactory设置,但那些对象将无法作为bean访问。任何的意见都将会有帮助。我确信可能有一个简单的解决方案。

1 个答案:

答案 0 :(得分:0)

只需将您的绑定等添加为@Bean,而不是自己声明。

添加RabbitAdmin @Bean,它会在建立连接时自动执行声明。

修改

回应你的评论......

但是,您正在执行自己的声明:

admin.declareQueue(q);
admin.declareBinding(...

除非您添加try / catch,否则如果代理不可用,这些将失败。您也可以在管理员上设置ignoreDeclarationExceptions,但您实际上不需要自己做这些声明。一旦容器建立连接,管理员就会自动声明它们。

<强> EDIT2

  

他们为什么会被宣布? ...

因为这是它的设计方式;请阅读the documentation向下滚动以查看Binding等的java配置。

RabbitAdmin(如果在上下文中声明)将自身注册为连接侦听器。建立连接后,管理员会在上下文中查找所有QueueExchangeBinding @Bean,并在建立连接时声明它们。

你通过直接从bean定义绑定来破坏这个“懒惰”声明,这需要代理可用,如果没有连接,上下文将无法初始化。

只需在上下文中声明所需的Binding,管理员将在代理可用时为您处理。监听器容器将根据其recoveryInterval继续尝试连接,并且在最终成功时将发生声明。