[Spring整合JMS(二)——三種消息監聽器](http://elim.iteye.com/blog/1893676)
## 1.3?????消息監聽器MessageListener
???????在Spring整合JMS的應用中我們在定義消息監聽器的時候一共可以定義三種類型的消息監聽器,分別是MessageListener、SessionAwareMessageListener和MessageListenerAdapter。下面就分別來介紹一下這幾種類型的區別。
### 1.3.1??MessageListener
MessageListener是最原始的消息監聽器,它是JMS規范中定義的一個接口。其中定義了一個用于處理接收到的消息的onMessage方法,該方法只接收一個Message參數。我們前面在講配置消費者的時候用的消息監聽器就是MessageListener,代碼如下:
Java代碼??
1. import?javax.jms.JMSException;??
2. import?javax.jms.Message;??
3. import?javax.jms.MessageListener;??
4. import?javax.jms.TextMessage;??
5. ???
6. public?class?ConsumerMessageListener?implements?MessageListener?{??
7. ???
8. ????public?void?onMessage(Message?message)?{??
9. ????????//這里我們知道生產者發送的就是一個純文本消息,所以這里可以直接進行強制轉換,或者直接把onMessage方法的參數改成Message的子類TextMessage??
10. ????????TextMessage?textMsg?=?(TextMessage)?message;??
11. ????????System.out.println("接收到一個純文本消息。");??
12. ????????try?{??
13. ????????????System.out.println("消息內容是:"?+?textMsg.getText());??
14. ????????}?catch?(JMSException?e)?{??
15. ????????????e.printStackTrace();??
16. ????????}??
17. ????}??
18. ???
19. }??
### 1.3.2??SessionAwareMessageListener
SessionAwareMessageListener是Spring為我們提供的,它不是標準的JMS MessageListener。MessageListener的設計只是純粹用來接收消息的,假如我們在使用MessageListener處理接收到的消息時我們需要發送一個消息通知對方我們已經收到這個消息了,那么這個時候我們就需要在代碼里面去重新獲取一個Connection或Session。SessionAwareMessageListener的設計就是為了方便我們在接收到消息后發送一個回復的消息,它同樣為我們提供了一個處理接收到的消息的onMessage方法,但是這個方法可以同時接收兩個參數,一個是表示當前接收到的消息Message,另一個就是可以用來發送消息的Session對象。先來看一段代碼:
Java代碼??
1. package?com.tiantian.springintejms.listener;??
2. ???
3. import?javax.jms.Destination;??
4. import?javax.jms.JMSException;??
5. import?javax.jms.Message;??
6. import?javax.jms.MessageProducer;??
7. import?javax.jms.Session;??
8. import?javax.jms.TextMessage;??
9. ???
10. import?org.springframework.jms.listener.SessionAwareMessageListener;??
11. ???
12. public?class?ConsumerSessionAwareMessageListener?implements??
13. ????????SessionAwareMessageListener?{??
14. ???
15. ????private?Destination?destination;??
16. ??????
17. ????public?void?onMessage(TextMessage?message,?Session?session)?throws?JMSException?{??
18. ????????System.out.println("收到一條消息");??
19. ????????System.out.println("消息內容是:"?+?message.getText());??
20. ????????MessageProducer?producer?=?session.createProducer(destination);??
21. ????????Message?textMessage?=?session.createTextMessage("ConsumerSessionAwareMessageListener。。。");??
22. ????????producer.send(textMessage);??
23. ????}??
24. ???
25. ????public?Destination?getDestination()?{??
26. ????????returndestination;??
27. ????}??
28. ???
29. ????public?void?setDestination(Destination?destination)?{??
30. ????????this.destination?=?destination;??
31. ????}??
32. ???
33. }??
???????在上面代碼中我們定義了一個SessionAwareMessageListener,在這個Listener中我們在接收到了一個消息之后,利用對應的Session創建了一個到destination的生產者和對應的消息,然后利用創建好的生產者發送對應的消息。
???????接著我們在Spring的配置文件中配置該消息監聽器將處理來自一個叫sessionAwareQueue的目的地的消息,并且往該MessageListener中通過set方法注入其屬性destination的值為queueDestination。這樣當我們的SessionAwareMessageListener接收到消息之后就會往queueDestination發送一個消息。
Xml代碼??
1. xml?version="1.0"?encoding="UTF-8"?>??
2. beans?xmlns="http://www.springframework.org/schema/beans"??
3. ????xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"?xmlns:context="http://www.springframework.org/schema/context"??
4. ????xmlns:jms="http://www.springframework.org/schema/jms"??
5. ????xsi:schemaLocation="http://www.springframework.org/schema/beans??
6. ?????http://www.springframework.org/schema/beans/spring-beans-3.0.xsd??
7. ?????http://www.springframework.org/schema/context??
8. ?????http://www.springframework.org/schema/context/spring-context-3.0.xsd??
9. ????http://www.springframework.org/schema/beans?http://www.springframework.org/schema/beans/spring-beans-3.0.xsd??
10. ????http://www.springframework.org/schema/jms?http://www.springframework.org/schema/jms/spring-jms-3.0.xsd">??
11. ???
12. ????context:component-scan?base-package="com.tiantian"?/>???
13. ??????
14. ????bean?id="jmsTemplate"?class="org.springframework.jms.core.JmsTemplate">??
15. ??????????
16. ????????property?name="connectionFactory"?ref="connectionFactory"/>??
17. ????bean>??
18. ??????
19. ??????
20. ????bean?id="targetConnectionFactory"?class="org.apache.activemq.ActiveMQConnectionFactory">??
21. ????????property?name="brokerURL"?value="tcp://localhost:61616"/>??
22. ????bean>??
23. ??????
24. ??????
25. ????bean?id="connectionFactory"?class="org.springframework.jms.connection.SingleConnectionFactory">??
26. ??????????
27. ????????property?name="targetConnectionFactory"?ref="targetConnectionFactory"/>??
28. ????bean>??
29. ??????
30. ??????
31. ????bean?id="queueDestination"?class="org.apache.activemq.command.ActiveMQQueue">??
32. ????????constructor-arg>??
33. ????????????value>queuevalue>??
34. ????????constructor-arg>??
35. ????bean>??
36. ??????
37. ????bean?id="sessionAwareQueue"?class="org.apache.activemq.command.ActiveMQQueue">??
38. ????????constructor-arg>??
39. ????????????value>sessionAwareQueuevalue>??
40. ????????constructor-arg>??
41. ????bean>??
42. ??????
43. ????bean?id="consumerMessageListener"?class="com.tiantian.springintejms.listener.ConsumerMessageListener"/>??
44. ??????
45. ????bean?id="consumerSessionAwareMessageListener"?class="com.tiantian.springintejms.listener.ConsumerSessionAwareMessageListener">??
46. ????????property?name="destination"?ref="queueDestination"/>??
47. ????bean>??
48. ??????
49. ????bean?id="jmsContainer"????????class="org.springframework.jms.listener.DefaultMessageListenerContainer">??
50. ????????property?name="connectionFactory"?ref="connectionFactory"?/>??
51. ????????property?name="destination"?ref="queueDestination"?/>??
52. ????????property?name="messageListener"?ref="consumerMessageListener"?/>??
53. ????bean>??
54. ??????
55. ????bean?id="sessionAwareListenerContainer"??
56. ????????class="org.springframework.jms.listener.DefaultMessageListenerContainer">??
57. ????????property?name="connectionFactory"?ref="connectionFactory"?/>??
58. ????????property?name="destination"?ref="sessionAwareQueue"?/>??
59. ????????property?name="messageListener"?ref="consumerSessionAwareMessageListener"?/>??
60. ????bean>??
61. beans>??
???????接著我們來做一個測試,測試代碼如下:
Java代碼??
1. @RunWith(SpringJUnit4ClassRunner.class)??
2. @ContextConfiguration("/applicationContext.xml")??
3. public?class?ProducerConsumerTest?{??
4. ???
5. ????@Autowired??
6. ????private?ProducerService?producerService;??
7. ????@Autowired??
8. ????@Qualifier("sessionAwareQueue")??
9. ????private?Destination?sessionAwareQueue;??
10. ??????
11. ????@Test??
12. ????public?void?testSessionAwareMessageListener()?{??
13. ????????producerService.sendMessage(sessionAwareQueue,?"測試SessionAwareMessageListener");??
14. ????}??
15. ??????
16. }??
???????在上述測試代碼中,我們通過前面定義好的生產者往我們定義好的SessionAwareMessageListener監聽的sessionAwareQueue發送了一個消息。程序運行之后控制臺輸出如下:

?
???????這說明我們已經成功的往sessionAwareQueue發送了一條純文本消息,消息會被ConsumerSessionAwareMessageListener的onMessage方法進行處理,在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的構造方法參數指定,如:
Xml代碼??
1. ??
2. ????bean?id="messageListenerAdapter"?class="org.springframework.jms.listener.adapter.MessageListenerAdapter">??
3. ????????constructor-arg>??
4. ????????????bean?class="com.tiantian.springintejms.listener.ConsumerListener"/>??
5. ????????constructor-arg>??
6. ????bean>??
???????也可以通過它的delegate屬性來指定,如:
Xml代碼??
1. ??
2. ????bean?id="messageListenerAdapter"?class="org.springframework.jms.listener.adapter.MessageListenerAdapter">??
3. ????????property?name="delegate">??
4. ????????????bean?class="com.tiantian.springintejms.listener.ConsumerListener"/>??
5. ????????property>??
6. ????????property?name="defaultListenerMethod"?value="receiveMessage"/>??
7. ????bean>??
???????前面說了如果我們指定的這個目標處理器是一個MessageListener或者是一個SessionAwareMessageListener的時候Spring將直接利用接收到的Message對象作為方法參數調用它們的onMessage方法。但是如果指定的目標處理器是一個普通的Java類時Spring將利用Message進行了類型轉換之后的對象作為參數通過反射去調用真正的目標處理器的處理方法,那么Spring是如何知道該調用哪個方法呢?這是通過MessageListenerAdapter的defaultListenerMethod屬性來決定的,當我們沒有指定該屬性時,Spring會默認調用目標處理器的handleMessage方法。
???????接下來我們來看一個示例,假設我們有一個普通的Java類ConsumerListener,其對應有兩個方法,handleMessage和receiveMessage,其代碼如下:
Java代碼??
1. package?com.tiantian.springintejms.listener;??
2. ???
3. public?class?ConsumerListener?{??
4. ???
5. ????public?void?handleMessage(String?message)?{??
6. ????????System.out.println("ConsumerListener通過handleMessage接收到一個純文本消息,消息內容是:"?+?message);??
7. ????}??
8. ??????
9. ????public?void?receiveMessage(String?message)?{??
10. ????????System.out.println("ConsumerListener通過receiveMessage接收到一個純文本消息,消息內容是:"?+?message);??
11. ????}??
12. ??????
13. }??
???????假設我們要把它作為一個消息監聽器來監聽發送到adapterQueue的消息,這個時候我們就可以定義一個對應的MessageListenerAdapter來把它當做一個MessageListener使用。
Xml代碼??
1. ??
2. bean?id="messageListenerAdapter"?class="org.springframework.jms.listener.adapter.MessageListenerAdapter">??
3. ????property?name="delegate">??
4. ????????bean?class="com.tiantian.springintejms.listener.ConsumerListener"/>??
5. ????property>??
6. ????property?name="defaultListenerMethod"?value="receiveMessage"/>??
7. bean>??
???????當然,有了MessageListener之后我們還需要配置其對應的MessageListenerContainer,這里配置如下:
Xml代碼??
1. ??????
2. ????bean?id="messageListenerAdapterContainer"?class="org.springframework.jms.listener.DefaultMessageListenerContainer">??
3. ????????property?name="connectionFactory"?ref="connectionFactory"/>??
4. ????????property?name="destination"?ref="adapterQueue"/>??
5. ????????property?name="messageListener"?ref="messageListenerAdapter"/>??
6. ????bean>??
7. ??
8. ??
9. ????bean?id="adapterQueue"?class="org.apache.activemq.command.ActiveMQQueue">??
10. ????????constructor-arg>??
11. ????????????value>adapterQueuevalue>??
12. ????????constructor-arg>??
13. ????bean>??
???????在上面的MessageListenerAdapter中我們指定了其defaultListenerMethod屬性的值為receiveMessage,所以當MessageListenerAdapter接收到消息之后會自動的調用我們指定的ConsumerListener的receiveMessage方法。
???????針對于上述代碼我們定義測試代碼如下:
Java代碼??
1. package?com.tiantian.springintejms.test;??
2. ???
3. import?javax.jms.Destination;??
4. ???
5. import?org.junit.Test;??
6. import?org.junit.runner.RunWith;??
7. import?org.springframework.beans.factory.annotation.Autowired;??
8. import?org.springframework.beans.factory.annotation.Qualifier;??
9. import?org.springframework.test.context.ContextConfiguration;??
10. import?org.springframework.test.context.junit4.SpringJUnit4ClassRunner;??
11. ???
12. import?com.tiantian.springintejms.service.ProducerService;??
13. ???
14. @RunWith(SpringJUnit4ClassRunner.class)??
15. @ContextConfiguration("/applicationContext.xml")??
16. public?class?ProducerConsumerTest?{??
17. ??
18. ????@Autowired??
19. ????@Qualifier("adapterQueue")??
20. ????private?Destination?adapterQueue;??
21. ??
22. ????@Test??
23. ????public?void?testMessageListenerAdapter()?{??
24. ????????producerService.sendMessage(adapterQueue,?"測試MessageListenerAdapter");??
25. ????}??
26. ??????
27. }??
???????這時候我們會看到控制臺輸出如下:

????????如果我們不指定MessageListenerAdapter的defaultListenerMethod屬性,那么在運行上述代碼時控制臺會輸出如下結果:

????????MessageListenerAdapter除了會自動的把一個普通Java類當做MessageListener來處理接收到的消息之外,**其另外一個主要的功能是可以自動的發送返回消息**。
?????當我們用于處理接收到的消息的方法的返回值不為空的時候,Spring會自動將它封裝為一個JMS Message,然后自動進行回復。那么這個時候這個回復消息將發送到哪里呢?這主要有兩種方式可以指定。
???????第一,可以通過發送的Message的setJMSReplyTo方法指定該消息對應的回復消息的目的地。這里我們把我們的生產者發送消息的代碼做一下修改,在發送消息之前先指定該消息對應的回復目的地為一個叫responseQueue的隊列目的地,具體代碼如下所示:
Java代碼??
1. package?com.tiantian.springintejms.service.impl;??
2. ???
3. import?javax.jms.Destination;??
4. import?javax.jms.JMSException;??
5. import?javax.jms.Message;??
6. import?javax.jms.Session;??
7. import?javax.jms.TextMessage;??
8. ???
9. import?org.springframework.beans.factory.annotation.Autowired;??
10. import?org.springframework.beans.factory.annotation.Qualifier;??
11. import?org.springframework.jms.core.JmsTemplate;??
12. import?org.springframework.jms.core.MessageCreator;??
13. import?org.springframework.stereotype.Component;??
14. ???
15. import?com.tiantian.springintejms.service.ProducerService;??
16. ???
17. @Component??
18. public?class?ProducerServiceImpl?implements?ProducerService?{???
19. ??
20. ????@Autowired??
21. ????private?JmsTemplate?jmsTemplate;??
22. ??
23. ????@Autowired??
24. ????@Qualifier("responseQueue")??
25. ????private?Destination?responseDestination;??
26. ??????
27. ????public?void?sendMessage(Destination?destination,?final?String?message)?{??
28. ????????System.out.println("---------------生產者發送消息-----------------");??
29. ????????System.out.println("---------------生產者發了一個消息:"?+?message);??
30. ????????jmsTemplate.send(destination,?new?MessageCreator()?{??
31. ????????????public?Message?createMessage(Session?session)?throws?JMSException?{??
32. ????????????????TextMessage?textMessage?=?session.createTextMessage(message);??
33. ????????????????textMessage.setJMSReplyTo(responseDestination);??
34. ????????????????return?textMessage;??
35. ????????????}??
36. ????????});??
37. ????}??
38. ???
39. }??
???????接著定義一個叫responseQueue的隊列目的地及其對應的消息監聽器和監聽容器。
Xml代碼??
1. ??
2. bean?id="responseQueue"?class="org.apache.activemq.command.ActiveMQQueue">??
3. ????constructor-arg>??
4. ????????value>responseQueuevalue>??
5. ????constructor-arg>??
6. bean>??
7. ??
8. ??
9. bean?id="responseQueueListener"?class="com.tiantian.springintejms.listener.ResponseQueueListener"/>??
10. ??
11. ??
12. bean?id="responseQueueMessageListenerContainer"?class="org.springframework.jms.listener.DefaultMessageListenerContainer">??
13. ????property?name="connectionFactory"?ref="connectionFactory"/>??
14. ????property?name="destination"?ref="responseQueue"/>??
15. ????property?name="messageListener"?ref="responseQueueListener"/>??
16. bean>??
???????ResponseQueueListener的定義如下所示:
Java代碼??
1. public?class?ResponseQueueListener?implements?MessageListener?{??
2. ???
3. ????public?void?onMessage(Message?message)?{??
4. ????????if?(message?instanceof?TextMessage)?{??
5. ????????????TextMessage?textMessage?=?(TextMessage)?message;??
6. ????????????try?{??
7. ????????????????System.out.println("接收到發送到responseQueue的一個文本消息,內容是:"?+?textMessage.getText());??
8. ????????????}?catch?(JMSException?e)?{??
9. ????????????????e.printStackTrace();??
10. ????????????}??
11. ????????}??
12. ????}??
13. ???
14. }??
????????接著把我們接收消息的ConsumerListener的receiveMessage方法改為如下:
Java代碼??
1. /**?
2. ?*?當返回類型是非null時MessageListenerAdapter會自動把返回值封裝成一個Message,然后進行回復?
3. ?*?@param?message?
4. ?*?@return?
5. ?*/??
6. public?String?receiveMessage(String?message)?{??
7. ????System.out.println("ConsumerListener通過receiveMessage接收到一個純文本消息,消息內容是:"?+?message);??
8. ????return?"這是ConsumerListener對象的receiveMessage方法的返回值。";??
9. }??
??????? 我們可以看到在上述負責接收消息的receiveMessage方法有一個非空的返回值。
???????接著我們運行我們的測試代碼,利用生產者往我們定義好的MessageListenerAdapter負責處理的adapterQueue目的地發送一個消息。測試代碼如下所示:
Java代碼??
1. @RunWith(SpringJUnit4ClassRunner.class)??
2. @ContextConfiguration("/applicationContext.xml")??
3. public?class?ProducerConsumerTest?{??
4. ???
5. ????@Autowired??
6. ????private?ProducerService?producerService;??
7. ??
8. ????@Qualifier("adapterQueue")??
9. ????@Autowired??
10. ????private?Destination?adapterQueue;?????
11. ??
12. ????@Test??
13. ????public?void?testMessageListenerAdapter()?{??
14. ????????producerService.sendMessage(adapterQueue,?"測試MessageListenerAdapter");??
15. ????}??
16. ??????
17. }??
???????運行上述測試代碼之后,控制臺輸出如下:

????????這說明我們的生產者發送消息被MessageListenerAdapter處理之后,MessageListenerAdapter確實把監聽器的返回內容封裝成一個Message往原Message通過setJMSReplyTo方法指定的回復目的地發送了一個消息。對于MessageListenerAdapter對應的監聽器處理方法返回的是一個null值或者返回類型是void的情況,MessageListenerAdapter是不會自動進行消息的回復的,有興趣的網友可以自己測試一下。
???????第二,通過MessageListenerAdapter的defaultResponseDestination屬性來指定。這里我們也來做一個測試,首先維持生產者發送消息的代碼不變,即發送消息前不通過Message的setJMSReplyTo方法指定消息的回復目的地;接著我們在定義MessageListenerAdapter的時候通過其defaultResponseDestination屬性指定其默認的回復目的地是“defaultResponseQueue”,并定義defaultResponseQueue對應的消息監聽器和消息監聽容器。
Xml代碼??
1. ??
2. bean?id="messageListenerAdapter"?class="org.springframework.jms.listener.adapter.MessageListenerAdapter">??
3. ????constructor-arg>??
4. ????????bean?class="com.tiantian.springintejms.listener.ConsumerListener"/>??
5. ????constructor-arg>?-->??
6. ????property?name="delegate">??
7. ????????bean?class="com.tiantian.springintejms.listener.ConsumerListener"/>??
8. ????property>??
9. ????property?name="defaultListenerMethod"?value="receiveMessage"/>??
10. ????property?name="defaultResponseDestination"?ref="defaultResponseQueue"/>??
11. bean>??
12. ??
13. ??
14. bean?id="messageListenerAdapterContainer"?class="org.springframework.jms.listener.DefaultMessageListenerContainer">??
15. ????property?name="connectionFactory"?ref="connectionFactory"/>??
16. ????property?name="destination"?ref="adapterQueue"/>??
17. ????property?name="messageListener"?ref="messageListenerAdapter"/>??
18. bean>??
19. ??
20. !--?默認的消息回復隊列?-->??
21. bean?id="defaultResponseQueue"?class="org.apache.activemq.command.ActiveMQQueue">??
22. ????constructor-arg>??
23. ????????value>defaultResponseQueuevalue>??
24. ????constructor-arg>??
25. bean>??
26. ??
27. ??
28. bean?id="defaultResponseQueueListener"?class="com.tiantian.springintejms.listener.DefaultResponseQueueListener"/>??
29. ??
30. ??
31. bean?id="defaultResponseQueueMessageListenerContainer"?class="org.springframework.jms.listener.DefaultMessageListenerContainer">??
32. ????property?name="connectionFactory"?ref="connectionFactory"/>??
33. ????property?name="destination"?ref="defaultResponseQueue"/>??
34. ????property?name="messageListener"?ref="defaultResponseQueueListener"/>??
35. bean>??
???????DefaultResponseQueueListener的代碼如下所示:
Java代碼??
1. package?com.tiantian.springintejms.listener;??
2. ???
3. import?javax.jms.JMSException;??
4. import?javax.jms.Message;??
5. import?javax.jms.MessageListener;??
6. import?javax.jms.TextMessage;??
7. ???
8. public?class?DefaultResponseQueueListener?implements?MessageListener?{??
9. ???
10. ????public?void?onMessage(Message?message)?{??
11. ????????if?(message?instanceof?TextMessage)?{??
12. ????????????TextMessage?textMessage?=?(TextMessage)?message;??
13. ????????????try?{??
14. ????????????????System.out.println("DefaultResponseQueueListener接收到發送到defaultResponseQueue的一個文本消息,內容是:"?+?textMessage.getText());??
15. ????????????}?catch?(JMSException?e)?{??
16. ????????????????e.printStackTrace();??
17. ????????????}??
18. ????????}??
19. ????}??
20. ???
21. }??
???????這時候運行如下測試代碼:
Java代碼??
1. @Test??
2. public?void?testMessageListenerAdapter()?{??
3. ????producerService.sendMessage(adapterQueue,?"測試MessageListenerAdapter");??
4. }??
???????控制臺將輸出如下內容:

????????這說明MessageListenerAdapter會自動把真正的消息處理器返回的非空內容封裝成一個Message發送回復消息到通過defaultResponseDestination屬性指定的默認消息回復目的地。
???????既然我們可以通過兩種方式來指定MessageListenerAdapter自動發送回復消息的目的地,那么當我們兩種方式都指定了而且它們的目的地還不一樣的時候會怎么發送呢?是兩個都發還是只發其中的一個呢?關于這部分的測試我這里就不贅述了,有興趣的網友可以自己進行。這里我可以直接的告訴大家,當兩種方式都指定了消息的回復目的地的時候使用發送消息的setJMSReplyTo方法指定的目的地將具有較高的優先級,MessageListenerAdapter將只往該方法指定的消息回復目的地發送回復消息。