我有一个基于Spring 3.0.5构建的应用程序,它使用JMS来交换消息。接收消息的bean使用jms
命名空间进行配置。该课程看起来像这样
class MyService {
public void receive(String msg) {
...
}
}
Spring配置如下所示
<jms:listener-container destination-type="queue">
<jms:listener destination="queue.test" ref="myService" method="receive"/>
</jms:listener-container>
但是,当我更改receive方法以获取Message
对象时,不再调用该方法。
class MyService {
public void receive(TextMessage msg) {
...
}
}
我意识到我可以使用MessageListenerAdapter
,但这是更多的配置开销,我只是想知道为什么这不起作用。
非常感谢任何见解。
谢
答案 0 :(得分:3)
<jms:listener>
配置会自动为您创建MessageListenerAdapter
,因此您无需明确配置它。
您的问题是MessageListenerAdapter
旨在将您的代码与JMS API完全分离。 <jms:listener>
中的目标方法必须声明MessageListenerAdapter
允许的参数类型之一(请参阅docs),它代表消息的可能有效负载类型,即String
之一,Serializable
,byte[]
或Map
。
如果要接收原始JMS TextMessage
对象,则侦听器类必须实现MessageListener
或SessionAwareMessageListener
。这使它成为一个“适当的”JMS监听器。在这种情况下,method
配置变得多余,您可以使用:
<jms:listener destination="queue.test" ref="myService"/>
我真的很惊讶Spring发现你的receive
方法的参数类型无效时没有抛出异常。
答案 1 :(得分:3)
我已经弄清楚,为了让MessageListenerAdapter
不转换邮件,messageConverter
属性必须设置为null
。但是,使用命名空间配置时,无法禁用自动创建的默认消息转换器。
AbstractListenerContainerParser
中的代码检查message-converter
的{{1}}属性是否未设置或指向有效的bean。否则,<jms:listener-container>
被实例化。
要解决此问题,我已创建了SimpleMessageAdapter
来解决问题
NoopMessageConverter
然后像这样配置public class NoopMessageConverter implements MessageConverter {
@Override
public Message toMessage(Object object, Session session)
throws JMSException, MessageConversionException {
return (Message) object;
}
@Override
public Object fromMessage(Message message)
throws JMSException, MessageConversionException {
return message;
}
}
<jms:listener-container>
然后您可以按如下方式创建bean,并调用<bean id="noopMessageConverter" class="NoopMessageConverter"/>
<jms:listener-container message-converter="noopMessageConverter">
<jms:listener destination="queue.test" ref="myService" method="receive"/>
</jms:listener-container>
方法
receive