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访问。任何的意见都将会有帮助。我确信可能有一个简单的解决方案。
答案 0 :(得分:0)
只需将您的绑定等添加为@Bean
,而不是自己声明。
添加RabbitAdmin
@Bean
,它会在建立连接时自动执行声明。
修改强>
回应你的评论......
但是,您正在执行自己的声明:
admin.declareQueue(q);
admin.declareBinding(...
除非您添加try / catch,否则如果代理不可用,这些将失败。您也可以在管理员上设置ignoreDeclarationExceptions
,但您实际上不需要自己做这些声明。一旦容器建立连接,管理员就会自动声明它们。
<强> EDIT2 强>:
他们为什么会被宣布? ...
因为这是它的设计方式;请阅读the documentation向下滚动以查看Binding
等的java配置。
RabbitAdmin
(如果在上下文中声明)将自身注册为连接侦听器。建立连接后,管理员会在上下文中查找所有Queue
,Exchange
和Binding
@Bean
,并在建立连接时声明它们。
你通过直接从bean定义绑定来破坏这个“懒惰”声明,这需要代理可用,如果没有连接,上下文将无法初始化。
只需在上下文中声明所需的Binding
,管理员将在代理可用时为您处理。监听器容器将根据其recoveryInterval
继续尝试连接,并且在最终成功时将发生声明。