Java 使用SpringJMS命名空间时未调用方法

Java 使用SpringJMS命名空间时未调用方法,java,spring,jms,Java,Spring,Jms,我有一个基于Spring3.0.5构建的应用程序,它使用JMS交换消息。通过使用jms名称空间配置接收消息的bean。这个班看起来像这样 class MyService { public void receive(String msg) { ... } } <jms:listener-container destination-type="queue"> <jms:listener destination="queue.test" ref=

我有一个基于Spring3.0.5构建的应用程序,它使用JMS交换消息。通过使用
jms
名称空间配置接收消息的bean。这个班看起来像这样

class MyService {
    public void receive(String msg) {
        ...
    }
}
<jms:listener-container destination-type="queue">
  <jms:listener destination="queue.test" ref="myService" method="receive"/>
</jms:listener-container>
<bean id="noopMessageConverter" class="NoopMessageConverter"/>

<jms:listener-container message-converter="noopMessageConverter">
    <jms:listener destination="queue.test" ref="myService" method="receive"/>
</jms:listener-container>
Spring配置如下所示

class MyService {
    public void receive(String msg) {
        ...
    }
}
<jms:listener-container destination-type="queue">
  <jms:listener destination="queue.test" ref="myService" method="receive"/>
</jms:listener-container>
<bean id="noopMessageConverter" class="NoopMessageConverter"/>

<jms:listener-container message-converter="noopMessageConverter">
    <jms:listener destination="queue.test" ref="myService" method="receive"/>
</jms:listener-container>
我意识到我可以只使用
MessageListenerAdapter
,但这会增加配置开销,我只是想知道为什么这不起作用

非常感谢您的任何见解

Frank

配置会自动为您创建一个
MessageListenerAdapter
,因此您无需显式配置

您的问题是
MessageListenerAdapter
的设计目的是将您的代码与JMS API完全解耦。
中的目标方法必须声明
MessageListenerAdapter
(请参阅)允许的参数类型之一,该参数类型表示消息的可能负载类型,即
字符串
可序列化
字节[]
映射
中的一种

如果希望接收原始JMS
TextMessage
对象,则侦听器类必须实现
MessageListener
SessionAwareMessageListener
。这使它成为一个“合适的”JMS侦听器。在这种情况下,
方法
配置变得多余,您只需使用:

<jms:listener destination="queue.test" ref="myService"/>


实际上,我很惊讶Spring在发现您的
receive
方法的参数类型无效时没有抛出异常。

我发现,要使
MessageListenerAdapter
不转换消息,必须将
messageConverter
属性设置为
null
。但是,在使用名称空间配置时,无法禁用自动创建的默认消息转换器

AbstractListenerContainerParser
中的代码检查
消息转换器
属性是否未设置或指向有效bean。否则将实例化一个
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;
    }
}
然后像这样配置

class MyService {
    public void receive(String msg) {
        ...
    }
}
<jms:listener-container destination-type="queue">
  <jms:listener destination="queue.test" ref="myService" method="receive"/>
</jms:listener-container>
<bean id="noopMessageConverter" class="NoopMessageConverter"/>

<jms:listener-container message-converter="noopMessageConverter">
    <jms:listener destination="queue.test" ref="myService" method="receive"/>
</jms:listener-container>

关键是
MessageListenerAdapter
完全能够调用一个需要原始
Message
对象的方法。这些文档甚至包含一个带有
DefaultTextMessageDelegate
的示例。在我的情况下,我需要访问消息属性。实现
MessageListener
接口意味着该类中只能有一个方法,然后需要将传入消息从多个队列分派到其他方法。我猜
配置了默认的
MessageListenerAdapter
,但为了获取原始消息,可能需要禁用内容通过将消息转换器设置为
null
进行提取。然而,这在
中似乎是不可能的。