Spring 4.1 @JmsListener 配置
Posted
技术标签:
【中文标题】Spring 4.1 @JmsListener 配置【英文标题】:Spring 4.1 @JmsListener configuration 【发布时间】:2014-11-12 01:01:42 【问题描述】:我想将 Spring 4.1 中提供的新注释和特性用于需要 JMS 侦听器的应用程序。
我已经仔细阅读了Spring 4.1 JMS improvements post 中的注释,但我仍然想念@JmsListener
和DestinationResolver
之间的关系,以及我将如何设置应用程序以指示正确的Destination
或Endpoint
.
这是@JmsListener 的建议用法
@Component
public class MyService
@JmsListener(containerFactory = "myContainerFactory", destination = "myQueue")
public void processOrder(String data) ...
现在,我不能在我的实际代码中使用它,因为需要使用 Environment.getProperty()
从配置文件中读取“myQueue”。
我可以使用DestinationResolver
设置一个适当的 myContainerFactory,但大多数情况下,如果您不需要 JNDI 在应用服务器中查找队列并且不需要做一些自定义,您似乎只需使用DynamicDestinationResolver
回复逻辑。我只是想了解 Spring 如何让我使用 @JmsListener
注释以参数化方式指示队列的名称。
在博客文章的后面,我找到了对这个配置器的引用:
@Configuration
@EnableJms
public class AppConfig implements JmsListenerConfigurer
@Override
public void configureJmsListeners(JmsListenerEndpointRegistrar registrar)
registrar.setDefaultContainerFactory(defaultContainerFactory());
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
endpoint.setDestination("anotherQueue");
endpoint.setMessageListener(message ->
// processing
);
registrar.registerEndpoint(endpoint);
现在,这有点道理,我可以看到这将允许我在运行时从一些外部字符串设置目标,但这似乎与使用 @JmsListener
冲突,因为它似乎覆盖了在上面的代码中注释有利于endpoint.setMessageListener
。
关于如何使用@JmsListener
指定适当队列名称的任何提示?
【问题讨论】:
使用占位符。destination="$name.of.your.property"
.
我宁愿不使用PropertyPlaceHolderConfiguration
来支持Environment.getProperty
,但显然我不能将该路由作为注释的参数。
实际上,您将使用PropertySourcePlaceHolderConfigurer
,它与Environment.getProperty
的作用基本相同(它会咨询所有PropertySource
s。您能否详细说明为什么您更喜欢Environment.getProperty
而不是占位符这个案子?
为什么@PropertySource
不能与占位符一起使用?它的工作原理相同。唯一的区别是您需要使用PropertySourcesPlaceHolderConfigurer
。因此,使用占位符这一事实并不意味着您不能再使用@PropertySource
。
我在这里与@M.Deinum +1,并有兴趣了解使用占位符的问题。
【参考方案1】:
另请注意,根据用例,您已经可以使用每个环境的属性文件和 PropertySourcesPlaceholderConfigurer 进行参数化
@JmsListener(destinations = "$some.key")
根据https://jira.spring.io/browse/SPR-12289
【讨论】:
这正是我所追求的。 @Value 注释演示了模板化,但文档中没有明确说明它更普遍可用。谢谢!【参考方案2】:如果人们将 @JmsListener
与 spring boot 一起使用,则不必配置 PropertySourcesPlaceholderConfigurer
。开箱即用
示例:
类
@JmsListener(destination = "$spring.activemq.queue.name")
public void receiveEntityMessage(final TextMessage message)
// process stuff
application.properties
spring.activemq.queue.name=some.weird.queue.name.that.does.not.exist
Spring 启动输出
[26-Aug;15:07:53.475]-[INFO ]-[,]-[DefaultMes]-[o.s.j.l.DefaultMessageListenerContainer ]-[931 ]-Successfully refreshed JMS Connection
[26-Aug;15:07:58.589]-[WARN ]-[,]-[DefaultMes]-[o.s.j.l.DefaultMessageListenerContainer ]-[880 ]-Setup of JMS message listener invoker failed for destination 'some.weird.queue.name.that.does.not.exist' - trying to recover. Cause: User user is not authorized to read from some.weird.queue.name.that.does.not.exist
[26-Aug;15:07:59.787]-[INFO ]-[,]-[DefaultMes]-[o.s.j.l.DefaultMessageListenerContainer ]-[931 ]-Successfully refreshed JMS Connection
[26-Aug;15:08:04.881]-[WARN ]-[,]-[DefaultMes]-[o.s.j.l.DefaultMessageListenerContainer ]-[880 ]-Setup of JMS message listener invoker failed for destination 'some.weird.queue.name.that.does.not.exist' - trying to recover. Cause: User user is not authorized to read from some.weird.queue.name.that.does.not.exist
这证明@JmsListener 能够从 application.properties 中获取属性值,而无需实际设置任何显式 PropertySourcesPlaceholderConfigurer
我希望这会有所帮助!
【讨论】:
【参考方案3】:您现在最终可以做到这一点,但这有点令人费解。您可以使用JmsListenerConfigurer
设置自定义JmsListenerEndpointRegistry
@Configuration
@EnableJms
public class AppConfig implements JmsListenerConfigurer
@Override
public void configureJmsListeners(JmsListenerEndpointRegistrar registrar)
registrar.setEndpointRegistry(customRegistry());
然后重写 registerListenerContainer 方法,类似于
public void registerListenerContainer(JmsListenerEndpoint endpoint, JmsListenerContainerFactory<?> factory)
// resolve destination according to whatever -> resolvedDestination
((AbstractJmsListenerEndpoint)endpoint).setDestination(resolvedDestination);
super.registerListenerContainer(endpoint, factory);
但我们可以做得更好。请关注/投票给SPR-12280
【讨论】:
这个有更新吗?票似乎已被拒绝,但现在已经 5 年了以上是关于Spring 4.1 @JmsListener 配置的主要内容,如果未能解决你的问题,请参考以下文章
如何在启动时以编程方式禁用 Spring @JmsListener
如何访问@JmsListener使用的Spring Boot中的活动JMS连接/会话
我怎样才能停止/启动/暂停@JmsListener(干净的方式)