`
234390216
  • 浏览: 10238061 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
博客专栏
A5ee55b9-a463-3d09-9c78-0c0cf33198cd
Oracle基础
浏览量:462862
Ad26f909-6440-35a9-b4e9-9aea825bd38e
springMVC介绍
浏览量:1775933
Ce363057-ae4d-3ee1-bb46-e7b51a722a4b
Mybatis简介
浏览量:1398696
Bdeb91ad-cf8a-3fe9-942a-3710073b4000
Spring整合JMS
浏览量:395144
5cbbde67-7cd5-313c-95c2-4185389601e7
Ehcache简介
浏览量:680152
Cc1c0708-ccc2-3d20-ba47-d40e04440682
Cas简介
浏览量:531116
51592fc3-854c-34f4-9eff-cb82d993ab3a
Spring Securi...
浏览量:1184910
23e1c30e-ef8c-3702-aa3c-e83277ffca91
Spring基础知识
浏览量:468710
4af1c81c-eb9d-365f-b759-07685a32156e
Spring Aop介绍
浏览量:151480
2f926891-9e7a-3ce2-a074-3acb2aaf2584
JAXB简介
浏览量:68321
社区版块
存档分类
最新评论

Spring整合JMS(二)——三种消息监听器

阅读更多

1.3     消息监听器MessageListener

       Spring整合JMS的应用中我们在定义消息监听器的时候一共可以定义三种类型的消息监听器,分别是MessageListenerSessionAwareMessageListenerMessageListenerAdapter。下面就分别来介绍一下这几种类型的区别。

1.3.1  MessageListener

MessageListener是最原始的消息监听器,它是JMS规范中定义的一个接口。其中定义了一个用于处理接收到的消息的onMessage方法,该方法只接收一个Message参数。我们前面在讲配置消费者的时候用的消息监听器就是MessageListener,代码如下:

 

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
 
public class ConsumerMessageListener implements MessageListener {
 
    public void onMessage(Message message) {
        //这里我们知道生产者发送的就是一个纯文本消息,所以这里可以直接进行强制转换,或者直接把onMessage方法的参数改成Message的子类TextMessage
        TextMessage textMsg = (TextMessage) message;
        System.out.println("接收到一个纯文本消息。");
        try {
            System.out.println("消息内容是:" + textMsg.getText());
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
 
}

  

1.3.2  SessionAwareMessageListener

SessionAwareMessageListenerSpring为我们提供的,它不是标准的JMS MessageListenerMessageListener的设计只是纯粹用来接收消息的,假如我们在使用MessageListener处理接收到的消息时我们需要发送一个消息通知对方我们已经收到这个消息了,那么这个时候我们就需要在代码里面去重新获取一个ConnectionSessionSessionAwareMessageListener的设计就是为了方便我们在接收到消息后发送一个回复的消息,它同样为我们提供了一个处理接收到的消息的onMessage方法,但是这个方法可以同时接收两个参数,一个是表示当前接收到的消息Message,另一个就是可以用来发送消息的Session对象。先来看一段代码:

package com.tiantian.springintejms.listener;
 
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
 
import org.springframework.jms.listener.SessionAwareMessageListener;
 
public class ConsumerSessionAwareMessageListener implements
        SessionAwareMessageListener<TextMessage> {
 
    private Destination destination;
    
    public void onMessage(TextMessage message, Session session) throws JMSException {
        System.out.println("收到一条消息");
        System.out.println("消息内容是:" + message.getText());
        MessageProducer producer = session.createProducer(destination);
        Message textMessage = session.createTextMessage("ConsumerSessionAwareMessageListener。。。");
        producer.send(textMessage);
    }
 
    public Destination getDestination() {
        returndestination;
    }
 
    public void setDestination(Destination destination) {
        this.destination = destination;
    }
 
}

 

       在上面代码中我们定义了一个SessionAwareMessageListener,在这个Listener中我们在接收到了一个消息之后,利用对应的Session创建了一个到destination的生产者和对应的消息,然后利用创建好的生产者发送对应的消息。

       接着我们在Spring的配置文件中配置该消息监听器将处理来自一个叫sessionAwareQueue的目的地的消息,并且往该MessageListener中通过set方法注入其属性destination的值为queueDestination。这样当我们的SessionAwareMessageListener接收到消息之后就会往queueDestination发送一个消息。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jms="http://www.springframework.org/schema/jms"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
     http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-3.0.xsd">
 
    <context:component-scan base-package="com.tiantian" /> 
    <!-- Spring提供的JMS工具类,它可以进行消息发送、接收等 -->
    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->
        <property name="connectionFactory" ref="connectionFactory"/>
    </bean>
    
    <!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供-->
    <bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="tcp://localhost:61616"/>
    </bean>
    
    <!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->
    <bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
        <!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->
        <property name="targetConnectionFactory" ref="targetConnectionFactory"/>
    </bean>
    
    <!--这个是队列目的地-->
    <bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg>
            <value>queue</value>
        </constructor-arg>
    </bean>
    <!--这个是sessionAwareQueue目的地-->
    <bean id="sessionAwareQueue" class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg>
            <value>sessionAwareQueue</value>
        </constructor-arg>
    </bean>
    <!-- 消息监听器 -->
    <bean id="consumerMessageListener" class="com.tiantian.springintejms.listener.ConsumerMessageListener"/>
    <!-- 可以获取session的MessageListener -->
    <bean id="consumerSessionAwareMessageListener" class="com.tiantian.springintejms.listener.ConsumerSessionAwareMessageListener">
        <property name="destination" ref="queueDestination"/>
    </bean>
    <!-- 消息监听容器 -->
    <bean id="jmsContainer"        class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <property name="connectionFactory" ref="connectionFactory" />
        <property name="destination" ref="queueDestination" />
        <property name="messageListener" ref="consumerMessageListener" />
    </bean>
    
    <bean id="sessionAwareListenerContainer"
        class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <property name="connectionFactory" ref="connectionFactory" />
        <property name="destination" ref="sessionAwareQueue" />
        <property name="messageListener" ref="consumerSessionAwareMessageListener" />
    </bean>
</beans>

 

 

       接着我们来做一个测试,测试代码如下:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/applicationContext.xml")
public class ProducerConsumerTest {
 
    @Autowired
    private ProducerService producerService;
    @Autowired
    @Qualifier("sessionAwareQueue")
    private Destination sessionAwareQueue;
    
    @Test
    public void testSessionAwareMessageListener() {
        producerService.sendMessage(sessionAwareQueue, "测试SessionAwareMessageListener");
    }
    
}

 

       在上述测试代码中,我们通过前面定义好的生产者往我们定义好的SessionAwareMessageListener监听的sessionAwareQueue发送了一个消息。程序运行之后控制台输出如下:



 

 

       这说明我们已经成功的往sessionAwareQueue发送了一条纯文本消息,消息会被ConsumerSessionAwareMessageListeneronMessage方法进行处理,在onMessage方法中ConsumerSessionAwareMessageListener就是简单的把接收到的纯文本信息的内容打印出来了,之后再往queueDestination发送了一个纯文本消息,消息内容是“ConsumerSessionAwareMessageListener…”,该消息随后就被ConsumerMessageListener处理了,根据我们的定义,在ConsumerMessageListener中也只是简单的打印了一下接收到的消息内容。

1.3.3  MessageListenerAdapter

MessageListenerAdapter类实现了MessageListener接口和SessionAwareMessageListener接口,它的主要作用是将接收到的消息进行类型转换,然后通过反射的形式把它交给一个普通的Java类进行处理。

       MessageListenerAdapter会把接收到的消息做如下转换:

       TextMessage转换为String对象;

       BytesMessage转换为byte数组;

       MapMessage转换为Map对象;

       ObjectMessage转换为对应的Serializable对象。

       既然前面说了MessageListenerAdapter会把接收到的消息做一个类型转换,然后利用反射把它交给真正的目标处理器——一个普通的Java类进行处理(如果真正的目标处理器是一个MessageListener或者是一个SessionAwareMessageListener,那么Spring将直接使用接收到的Message对象作为参数调用它们的onMessage方法,而不会再利用反射去进行调用),那么我们在定义一个MessageListenerAdapter的时候就需要为它指定这样一个目标类。这个目标类我们可以通过MessageListenerAdapter的构造方法参数指定,如:

<!-- 消息监听适配器 -->
    <bean id="messageListenerAdapter" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
        <constructor-arg>
            <bean class="com.tiantian.springintejms.listener.ConsumerListener"/>
        </constructor-arg>
    </bean>

 

 

       也可以通过它的delegate属性来指定,如:

<!-- 消息监听适配器 -->
    <bean id="messageListenerAdapter" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
        <property name="delegate">
            <bean class="com.tiantian.springintejms.listener.ConsumerListener"/>
        </property>
        <property name="defaultListenerMethod" value="receiveMessage"/>
    </bean>

 

 

       前面说了如果我们指定的这个目标处理器是一个MessageListener或者是一个SessionAwareMessageListener的时候Spring将直接利用接收到的Message对象作为方法参数调用它们的onMessage方法。但是如果指定的目标处理器是一个普通的Java类时Spring将利用Message进行了类型转换之后的对象作为参数通过反射去调用真正的目标处理器的处理方法,那么Spring是如何知道该调用哪个方法呢?这是通过MessageListenerAdapterdefaultListenerMethod属性来决定的,当我们没有指定该属性时,Spring会默认调用目标处理器的handleMessage方法。

       接下来我们来看一个示例,假设我们有一个普通的JavaConsumerListener,其对应有两个方法,handleMessagereceiveMessage,其代码如下:

package com.tiantian.springintejms.listener;
 
public class ConsumerListener {
 
    public void handleMessage(String message) {
        System.out.println("ConsumerListener通过handleMessage接收到一个纯文本消息,消息内容是:" + message);
    }
    
    public void receiveMessage(String message) {
        System.out.println("ConsumerListener通过receiveMessage接收到一个纯文本消息,消息内容是:" + message);
    }
    
}

 

       假设我们要把它作为一个消息监听器来监听发送到adapterQueue的消息,这个时候我们就可以定义一个对应的MessageListenerAdapter来把它当做一个MessageListener使用。

    <!-- 消息监听适配器 -->
    <bean id="messageListenerAdapter" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
        <property name="delegate">
            <bean class="com.tiantian.springintejms.listener.ConsumerListener"/>
        </property>
        <property name="defaultListenerMethod" value="receiveMessage"/>
    </bean>

 

       当然,有了MessageListener之后我们还需要配置其对应的MessageListenerContainer,这里配置如下:

    <!-- 消息监听适配器对应的监听容器 -->
    <bean id="messageListenerAdapterContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <property name="connectionFactory" ref="connectionFactory"/>
        <property name="destination" ref="adapterQueue"/>
        <property name="messageListener" ref="messageListenerAdapter"/><!-- 使用MessageListenerAdapter来作为消息监听器 -->
    </bean>

<!-- 用于测试消息监听适配器的队列目的地 -->
	<bean id="adapterQueue" class="org.apache.activemq.command.ActiveMQQueue">
		<constructor-arg>
			<value>adapterQueue</value>
		</constructor-arg>
	</bean>

 

       在上面的MessageListenerAdapter中我们指定了其defaultListenerMethod属性的值为receiveMessage,所以当MessageListenerAdapter接收到消息之后会自动的调用我们指定的ConsumerListenerreceiveMessage方法。

       针对于上述代码我们定义测试代码如下:

package com.tiantian.springintejms.test;
 
import javax.jms.Destination;
 
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
import com.tiantian.springintejms.service.ProducerService;
 
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/applicationContext.xml")
public class ProducerConsumerTest {

    @Autowired
    @Qualifier("adapterQueue")
    private Destination adapterQueue;

    @Test
    public void testMessageListenerAdapter() {
        producerService.sendMessage(adapterQueue, "测试MessageListenerAdapter");
    }
    
}

 

       这时候我们会看到控制台输出如下:



       
如果我们不指定MessageListenerAdapterdefaultListenerMethod属性,那么在运行上述代码时控制台会输出如下结果:



       
MessageListenerAdapter
除了会自动的把一个普通Java类当做MessageListener来处理接收到的消息之外,其另外一个主要的功能是可以自动的发送返回消息

     当我们用于处理接收到的消息的方法的返回值不为空的时候,Spring会自动将它封装为一个JMS Message,然后自动进行回复。那么这个时候这个回复消息将发送到哪里呢?这主要有两种方式可以指定。
      
第一,可以通过发送的MessagesetJMSReplyTo方法指定该消息对应的回复消息的目的地。这里我们把我们的生产者发送消息的代码做一下修改,在发送消息之前先指定该消息对应的回复目的地为一个叫responseQueue的队列目的地,具体代码如下所示:

package com.tiantian.springintejms.service.impl;
 
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import javax.jms.TextMessage;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.stereotype.Component;
 
import com.tiantian.springintejms.service.ProducerService;
 
@Component
public class ProducerServiceImpl implements ProducerService { 

    @Autowired
    private JmsTemplate jmsTemplate;

    @Autowired
    @Qualifier("responseQueue")
    private Destination responseDestination;
    
    public void sendMessage(Destination destination, final String message) {
        System.out.println("---------------生产者发送消息-----------------");
        System.out.println("---------------生产者发了一个消息:" + message);
        jmsTemplate.send(destination, new MessageCreator() {
            public Message createMessage(Session session) throws JMSException {
                TextMessage textMessage = session.createTextMessage(message);
                textMessage.setJMSReplyTo(responseDestination);
                return textMessage;
            }
        });
    }
 
}

 

       接着定义一个叫responseQueue的队列目的地及其对应的消息监听器和监听容器。

    <!-- 用于测试消息回复的 -->
    <bean id="responseQueue" class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg>
            <value>responseQueue</value>
        </constructor-arg>
    </bean>

    <!-- responseQueue对应的监听器 -->
    <bean id="responseQueueListener" class="com.tiantian.springintejms.listener.ResponseQueueListener"/>

    <!-- responseQueue对应的监听容器 -->
    <bean id="responseQueueMessageListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <property name="connectionFactory" ref="connectionFactory"/>
        <property name="destination" ref="responseQueue"/>
        <property name="messageListener" ref="responseQueueListener"/>
    </bean>

  

       ResponseQueueListener的定义如下所示:

public class ResponseQueueListener implements MessageListener {
 
    public void onMessage(Message message) {
        if (message instanceof TextMessage) {
            TextMessage textMessage = (TextMessage) message;
            try {
                System.out.println("接收到发送到responseQueue的一个文本消息,内容是:" + textMessage.getText());
            } catch (JMSException e) {
                e.printStackTrace();
            }
        }
    }
 
}

        接着把我们接收消息的ConsumerListener的receiveMessage方法改为如下:

	/**
	 * 当返回类型是非null时MessageListenerAdapter会自动把返回值封装成一个Message,然后进行回复
	 * @param message
	 * @return
	 */
	public String receiveMessage(String message) {
		System.out.println("ConsumerListener通过receiveMessage接收到一个纯文本消息,消息内容是:" + message);
		return "这是ConsumerListener对象的receiveMessage方法的返回值。";
	}

        我们可以看到在上述负责接收消息的receiveMessage方法有一个非空的返回值。

       接着我们运行我们的测试代码,利用生产者往我们定义好的MessageListenerAdapter负责处理的adapterQueue目的地发送一个消息。测试代码如下所示:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/applicationContext.xml")
public class ProducerConsumerTest {
 
    @Autowired
    private ProducerService producerService;

    @Qualifier("adapterQueue")
    @Autowired
    private Destination adapterQueue;   

    @Test
    public void testMessageListenerAdapter() {
        producerService.sendMessage(adapterQueue, "测试MessageListenerAdapter");
    }
    
}

 

       运行上述测试代码之后,控制台输出如下:

 



       
这说明我们的生产者发送消息被MessageListenerAdapter处理之后,MessageListenerAdapter确实把监听器的返回内容封装成一个Message往原Message通过setJMSReplyTo方法指定的回复目的地发送了一个消息。对于MessageListenerAdapter对应的监听器处理方法返回的是一个null值或者返回类型是void的情况,MessageListenerAdapter是不会自动进行消息的回复的,有兴趣的网友可以自己测试一下。

       第二,通过MessageListenerAdapterdefaultResponseDestination属性来指定。这里我们也来做一个测试,首先维持生产者发送消息的代码不变,即发送消息前不通过MessagesetJMSReplyTo方法指定消息的回复目的地;接着我们在定义MessageListenerAdapter的时候通过其defaultResponseDestination属性指定其默认的回复目的地是“defaultResponseQueue”,并定义defaultResponseQueue对应的消息监听器和消息监听容器。

    <!-- 消息监听适配器 -->
    <bean id="messageListenerAdapter" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
        <!-- <constructor-arg>
            <bean class="com.tiantian.springintejms.listener.ConsumerListener"/>
        </constructor-arg> -->
        <property name="delegate">
            <bean class="com.tiantian.springintejms.listener.ConsumerListener"/>
        </property>
        <property name="defaultListenerMethod" value="receiveMessage"/>
        <property name="defaultResponseDestination" ref="defaultResponseQueue"/>
    </bean>

    <!-- 消息监听适配器对应的监听容器 -->
    <bean id="messageListenerAdapterContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <property name="connectionFactory" ref="connectionFactory"/>
        <property name="destination" ref="adapterQueue"/>
        <property name="messageListener" ref="messageListenerAdapter"/><!-- 使用MessageListenerAdapter来作为消息监听器 -->
    </bean>

<!-- 默认的消息回复队列 -->
    <bean id="defaultResponseQueue" class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg>
            <value>defaultResponseQueue</value>
        </constructor-arg>
    </bean>

    <!-- defaultResponseQueue对应的监听器 -->
    <bean id="defaultResponseQueueListener" class="com.tiantian.springintejms.listener.DefaultResponseQueueListener"/>

    <!-- defaultResponseQueue对应的监听容器 -->
    <bean id="defaultResponseQueueMessageListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <property name="connectionFactory" ref="connectionFactory"/>
        <property name="destination" ref="defaultResponseQueue"/>
        <property name="messageListener" ref="defaultResponseQueueListener"/>
    </bean>

 

       DefaultResponseQueueListener的代码如下所示:

package com.tiantian.springintejms.listener;
 
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
 
public class DefaultResponseQueueListener implements MessageListener {
 
    public void onMessage(Message message) {
        if (message instanceof TextMessage) {
            TextMessage textMessage = (TextMessage) message;
            try {
                System.out.println("DefaultResponseQueueListener接收到发送到defaultResponseQueue的一个文本消息,内容是:" + textMessage.getText());
            } catch (JMSException e) {
                e.printStackTrace();
            }
        }
    }
 
}

 

       这时候运行如下测试代码:

    @Test
    public void testMessageListenerAdapter() {
        producerService.sendMessage(adapterQueue, "测试MessageListenerAdapter");
    }

 

       控制台将输出如下内容:

 



       
这说明MessageListenerAdapter会自动把真正的消息处理器返回的非空内容封装成一个Message发送回复消息到通过defaultResponseDestination属性指定的默认消息回复目的地。

       既然我们可以通过两种方式来指定MessageListenerAdapter自动发送回复消息的目的地,那么当我们两种方式都指定了而且它们的目的地还不一样的时候会怎么发送呢?是两个都发还是只发其中的一个呢?关于这部分的测试我这里就不赘述了,有兴趣的网友可以自己进行。这里我可以直接的告诉大家,当两种方式都指定了消息的回复目的地的时候使用发送消息的setJMSReplyTo方法指定的目的地将具有较高的优先级,MessageListenerAdapter将只往该方法指定的消息回复目的地发送回复消息。

 

附:

  • 大小: 4.9 KB
  • 大小: 4.5 KB
  • 大小: 4.4 KB
  • 大小: 7.1 KB
  • 大小: 7.8 KB
29
3
分享到:
评论
20 楼 234390216 2017-11-18  
h954080042y 写道
博主,我一个疑问!如果使用SessionAwareMessageListener的时候,我回复的目的地也是sessionAwareQueue,怎么办。这样他是不是应该发生死循环

<bean id="consumerSessionAwareMessageListener" class="com.upsoft.gismonitor.support.mq.listener.ConsumerSessionAwareMessageListener" >
		<property name="destination" ref="sessionAwareQueue" />
	</bean>

实践出真知。
一般也不会这么用,即使某些特殊场景有这种需求,也会在消息中加上特定标识的,避免死循环的。
19 楼 h954080042y 2017-11-17  
博主,我一个疑问!如果使用SessionAwareMessageListener的时候,我回复的目的地也是sessionAwareQueue,怎么办。这样他是不是应该发生死循环

<bean id="consumerSessionAwareMessageListener" class="com.upsoft.gismonitor.support.mq.listener.ConsumerSessionAwareMessageListener" >
		<property name="destination" ref="sessionAwareQueue" />
	</bean>
18 楼 远水孤云WHS 2017-05-16  
大神再接再厉,多出好文。膜拜
17 楼 路温舒 2016-07-31  
    
16 楼 sesdes 2016-01-22  
15 楼 234390216 2015-12-18  
fuyuda 写道
楼主,你的“当MessageListenerAdapter接收到消息之后会自动的调用我们指定的ConsumerListener的receiveMessage方法。”的那段,执行测试方法,报这个错:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'messageListenerAdapterContainer' defined in URL [file:/D:/MyDevPlace/mywebapp/WebContent/WEB-INF/classes/spring-config.xml]: Cannot resolve reference to bean 'adapterQueue' while setting bean property 'destination'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'adapterQueue' is defined
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1469)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:755)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:125)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:109)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:261)
at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:68)
at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:86)
at org.springframework.test.context.DefaultTestContext.getApplicationContext(DefaultTestContext.java:72)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:212)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:200)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:259)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:261)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:219)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:83)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:68)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:163)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'adapterQueue' is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:687)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1168)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:281)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351)
... 43 more

adapterQueue 貌似没有bean定义啊


那可能当时贴的代码不全,这个确实是需要的。
14 楼 fuyuda 2015-12-17  
楼主,你的“当MessageListenerAdapter接收到消息之后会自动的调用我们指定的ConsumerListener的receiveMessage方法。”的那段,执行测试方法,报这个错:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'messageListenerAdapterContainer' defined in URL [file:/D:/MyDevPlace/mywebapp/WebContent/WEB-INF/classes/spring-config.xml]: Cannot resolve reference to bean 'adapterQueue' while setting bean property 'destination'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'adapterQueue' is defined
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1469)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:755)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:125)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:109)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:261)
at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:68)
at org.springframework.test.context.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:86)
at org.springframework.test.context.DefaultTestContext.getApplicationContext(DefaultTestContext.java:72)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:212)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:200)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:259)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:261)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:219)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:83)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:68)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:163)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'adapterQueue' is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:687)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1168)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:281)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351)
... 43 more

adapterQueue 貌似没有bean定义啊
13 楼 dongdongmian 2015-11-16  
好像都是监听发送方发送消息的,请问楼主接收方的有没有这样的监听器可监听发送方是否发送了新消息?
12 楼 a542550187 2015-03-15  
按照你给的模板,我自己也总结一下
11 楼 ittianlai 2014-10-11  
10 楼 javatozhang 2014-09-16  
lz写的清晰易懂、受用呀!
9 楼 animo_itey 2014-04-11  
写的好阿 ,但是我有点看不懂    不知道为啥!-.-
... 先跟着敲一遍吧 ,,, 
8 楼 alston_king 2014-01-27  
对于这样的文章,我只能赞! 顶!!! 鄙视写一堆代码,不说明为啥的。
lz你太伟大了!!!!
7 楼 234390216 2013-08-07  
10008700 写道
博主    MessageListenerAdapter的receiveMessage方法自动回复的消息并不是TextMessage的而是ObjectMessage的  求解

你返回的是一个Object还是一个String呢?如果是一个普通Object的话,那么返回ObjectMessage是正常的,其他情况麻烦贴代码给我看一下。
6 楼 10008700 2013-08-06  
博主    MessageListenerAdapter的receiveMessage方法自动回复的消息并不是TextMessage的而是ObjectMessage的  求解
5 楼 234390216 2013-06-29  
llartemisll 写道
不错,已经等第三篇好几天了!呵呵!

这几天比较忙,第三篇估计得等到下周三以后吧。
4 楼 234390216 2013-06-29  
至尊宝_唯一 写道
ResponseQueueListener的onMessage的方法需要返回值才可以自动回复的想,写的很好,但是这段例子有点小瑕疵,等待连载三

ResponseQueueListener是用于监听返回消息的,这里没有问题。该有返回值的是MessageListenerAdapter对应的真正的消息监听器ConsumerListener用于接收消息的receiveMessage方法。
3 楼 llartemisll 2013-06-29  
不错,已经等第三篇好几天了!呵呵!
2 楼 至尊宝_唯一 2013-06-28  
ResponseQueueListener的onMessage的方法需要返回值才可以自动回复的想,写的很好,但是这段例子有点小瑕疵,等待连载三
1 楼 xhalg 2013-06-25  
不错的,顶!

相关推荐

    Spring整合JMS——实现收发消息

    本篇文章将详细探讨如何通过Spring框架整合JMS,特别是使用ActiveMQ作为消息代理来实现消息的收发功能。 首先,我们需要理解Spring对JMS的支持。Spring提供了`org.springframework.jms`包,包含了一系列接口和类,...

    Spring整合JMS(四)——事务管理

    本文将深入探讨如何在Spring中整合JMS并实现事务管理,以确保消息传递的可靠性和一致性。 首先,我们需要理解Spring的声明式事务管理。Spring提供了一种强大的声明式事务管理机制,它允许我们在不编写任何事务控制...

    Spring整合JMS(三)——MessageConverter介绍

    Spring提供了对JMS的全面支持,包括连接工厂配置、消息生产者、消费者以及消息转换器等。JMS允许应用程序通过消息中间件进行解耦通信,提高系统的可扩展性和可靠性。Spring JMS抽象了JMS API,提供了更易于使用的...

    spring整合jms+activemq

    此外,Spring还支持JMS监听器容器,使得消息的消费可以以非阻塞的方式进行,提高了系统的可扩展性和并发性能。 接下来,我们来看看如何集成ActivemQ。首先,需要在项目中引入ActivemQ的相关依赖,通常是在pom.xml...

    Spring整合JMS.doc

    此外,通过Spring的配置文件或Java配置,可以定义消息监听器(MessageListener),以便在接收到消息时执行相应的业务逻辑。 六、案例分析与实践建议 在实际开发中,结合Spring Boot的特性,可以进一步简化JMS与...

    activemq与spring整合发送jms消息入门实例

    在Java世界中,ActiveMQ和Spring的整合是企业级应用中常见的消息中间件解决方案,用于实现JMS(Java Message Service)消息传递。本教程将深入探讨如何将这两个强大的工具结合在一起,以创建一个简单的发送JMS消息的...

    spring boot整合JPA——demo

    本示例“spring boot整合JPA——demo”将演示如何在Spring Boot项目中配置和使用JPA。 首先,我们需要理解Spring Boot与JPA的关系。Spring Boot是基于Spring框架的快速开发工具,它通过自动化配置减少了常规设置...

    spring_jms

    在具体实践中,我们需要在`applicationContext.xml`中配置JMS连接工厂、目的地(队列或主题)、以及消息监听器。然后,创建消息生产者和消费者类,分别调用`JmsTemplate.send()`方法发送消息,和重写`onMessage()`...

    spring整合JMS-居于ActiveMQ实现

    Spring整合JMS基于ActiveMQ实现是一项常见的企业级应用开发任务,它涉及到Spring框架、Java消息服务(JMS)以及ActiveMQ消息中间件的使用。在本文中,我们将深入探讨这三个关键概念,以及如何将它们有效地结合在一起...

    Spring整合JMS

    在Spring和JMS整合后的应用中,可以使用JmsTemplate类来发送消息,或者注册消息监听器来处理接收到的消息。发布消息时,只需调用JmsTemplate的send方法并指定目的地即可。消息的监听通常通过实现了MessageListener...

    精通Eclipse整合Web开发——Struts,Spring,Hibernate,JBPM-part1

    精通Eclipse整合Web开发——Struts,Spring,Hibernate,JBPM 图书馆下载的,不是很清晰,如果介意的,请不要下载,不要拍砖。 总共有三部分。

    spring-jms入门

    - **MessageListenerContainer**:通过实现`MessageListener`接口,Spring容器会自动启动监听线程,接收到消息后调用监听器方法。 - **JmsTemplate.receive()**:阻塞式接收,调用后会等待直到有消息到达。 **7. ...

    jms整合spring工程

    - **Spring JMS模块**:Spring框架提供了一组JMS模板和监听器容器,简化了消息的生产和消费。 - **ConnectionFactory**:JMS API的核心对象,用于创建连接到消息代理的连接。 - **Destination**:表示消息的目的...

    消息中间件ActiveMQ及Spring整合JMS.docx

    【ActiveMQ和Spring整合JMS】的文档主要介绍了消息中间件的基本概念,特别是重点讨论了ActiveMQ和JMS的相关知识。消息中间件是用于不同分布式系统之间数据交流的工具,通过消息传递机制来扩展进程间的通信。ActiveMQ...

    Spring发送接收JMS消息

    Spring还允许创建消息驱动的POJO(Plain Old Java Object),这是一种简单的消息监听器实现,无需扩展特定接口。只需在POJO上添加`@JmsListener`注解即可。 ```java @Service public class MDPService { @...

    Java网络编程--基于Spring的JMS编程

    7. **消息驱动的POJO(MDP)**:Spring支持消息驱动的POJO,这是一种轻量级的监听器模式,使得任何实现了`MessageListener`的类都可以作为消息消费者。 在实际项目中,基于Spring的JMS编程可以帮助我们构建可扩展、...

    Spring 实现远程访问详解——jms和activemq

    JMS 支持两种消息传递模型: 点对点(point-to-point,简称 PTP) 发布/订阅(publish/subscribe,简称 pub/sub)。 这两种消息传递模型非常相似,但有以下区别: PTP 消息传递模型规定了一条消息只能传递给一个接收...

    JMS整合Spring实例

    在Spring的配置文件(如applicationContext.xml)中,我们需要配置JMS连接工厂、目的地(Topic或Queue)以及消息监听器容器。 ```xml &lt;bean id="jmsTemplate" class="org.springframework.jms.core....

    spring整合JMS实现同步收发消息(基于ActiveMQ的实现)

    Spring 整合 JMS 实现同步收发消息(基于 ActiveMQ 的实现) Spring 整合 JMS 实现同步收发消息是指在 Spring 框架下使用 JMS(Java Message Service)协议来实现消息的同步收发。JMS 是一个基于 Java 的消息服务 ...

Global site tag (gtag.js) - Google Analytics