问题描述
我有一个我不理解的奇怪情况。 我想决定要启用还是禁用SQS侦听器。 因此,我创建了一个带有定义的配置类:
@Bean
MyListener createListener(Features f){
return f.shouldListen() ? new RealListener() : new MockListener();
}
如您所见,我有这样的继承:
interface MyListener{}
class RealListener implements MyListener{
@SqsListener(...)
list handleMessage(SqsMessage message){
...
}
}
class MockListener implements MyListener{}
现在,有趣的部分:
有时有效。
在几次重新启动应用程序之后,将调用handleMessage()
方法,但是在大多数情况下,并非没有例外。队列已创建,所有权限均已到位。
为了使其正常工作,我需要从RealListener
方法返回createListener()
或将@SqsListener
注释移至MyListener
界面中的方法。两者都不是我的选择,因为启用模拟后,我不想调用AWS。
我尝试了条件豆的创建,但是由于Features
依赖于数据库(更确切地说,是间接的objectManager依赖关系),所以我无法使其工作。我尝试了抽象类而不是接口,但是没有运气。我尝试在RealListener
中注册beanfactoryPostProcessor
bean,但这也行不通(相同的entityManager
依赖问题)。我尝试将注释移至界面,并在启用了模拟功能后将@ConditionalOnBean
与@Primary
一起使用,以创建一个空的AmazonSqsClient
,但它不起作用。
我可以理解它是行不通的,因为必须使用@SqsListener
注释的方法为该类型的bean创建(而不是其超级类/接口类型),但是我有三个这样的bean,并且彩票-有时全部正常,有时一两个,但有时都不起作用。
您有什么建议吗?
解决方法
好吧...我已经找到了问题,但是知道发生了什么仍然很好。
因此...超类QueueMessageHandler
中有一个使用detectHandlerMethods(...)
方法的类AbstractMethodMessageHandler
。此方法使用MethodIntrospector.selectMethods()
选择要扫描的方法。当某些配置类中有@SqsListener
时,此类将考虑用@EnableSqs
注释的方法。
问题是,在我的项目中,@EnableSqs
批注位于某个文件中-而不是具有createListener(...)
方法的文件,也不是Spring Boot应用程序的主类。也就是说,可以在@EnableSqs
之前或之后加载带有MethodIntrospector.selectMethods()
的类。
输出为:
- 我不知道,为什么它在没有继承的情况下也能正常工作,而在继承时却不起作用
- 为解决此问题,我将
@EnableSqs
移到了项目的主类中