消息监听器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. public class ConsumerMessageListener implements MessageListener {
  6. public void onMessage(Message message) {
  7. //这里我们知道生产者发送的就是一个纯文本消息,所以这里可以直接进行强制转换,或者直接把onMessage方法的参数改成Message的子类TextMessage
  8. TextMessage textMsg = (TextMessage) message;
  9. System.out.println("接收到一个纯文本消息。");
  10. try {
  11. System.out.println("消息内容是:" + textMsg.getText());
  12. catch (JMSException e) {
  13. e.printStackTrace();
  14. }
  15. }
  16. }

1.3.2  SessionAwareMessageListener

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

Java代码  
  1. package com.tiantian.springintejms.listener;
  2. import javax.jms.Destination;
  3. import javax.jms.JMSException;
  4. import javax.jms.Message;
  5. import javax.jms.MessageProducer;
  6. import javax.jms.Session;
  7. import javax.jms.TextMessage;
  8. import org.springframework.jms.listener.SessionAwareMessageListener;
  9. public class ConsumerSessionAwareMessageListener implements
  10. SessionAwareMessageListener<TextMessage> {
  11. private Destination destination;
  12. public void onMessage(TextMessage message, Session session) throws JMSException {
  13. System.out.println("收到一条消息");
  14. System.out.println("消息内容是:" + message.getText());
  15. MessageProducer producer = session.createProducer(destination);
  16. Message textMessage = session.createTextMessage("ConsumerSessionAwareMessageListener。。。");
  17. producer.send(textMessage);
  18. }
  19. public Destination getDestination() {
  20. returndestination;
  21. }
  22. public void setDestination(Destination destination) {
  23. this.destination = destination;
  24. }
  25. }

在上面代码中我们定义了一个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. <context:component-scan base-package="com.tiantian" />
  12. <!-- Spring提供的JMS工具类,它可以进行消息发送、接收等 -->
  13. <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
  14. <!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->
  15. <property name="connectionFactory" ref="connectionFactory"/>
  16. </bean>
  17. <!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供-->
  18. <bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
  19. <property name="brokerURL" value="tcp://localhost:61616"/>
  20. </bean>
  21. <!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->
  22. <bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
  23. <!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->
  24. <property name="targetConnectionFactory" ref="targetConnectionFactory"/>
  25. </bean>
  26. <!--这个是队列目的地-->
  27. <bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">
  28. <constructor-arg>
  29. <value>queue</value>
  30. </constructor-arg>
  31. </bean>
  32. <!--这个是sessionAwareQueue目的地-->
  33. <bean id="sessionAwareQueue" class="org.apache.activemq.command.ActiveMQQueue">
  34. <constructor-arg>
  35. <value>sessionAwareQueue</value>
  36. </constructor-arg>
  37. </bean>
  38. <!-- 消息监听器 -->
  39. <bean id="consumerMessageListener" class="com.tiantian.springintejms.listener.ConsumerMessageListener"/>
  40. <!-- 可以获取session的MessageListener -->
  41. <bean id="consumerSessionAwareMessageListener" class="com.tiantian.springintejms.listener.ConsumerSessionAwareMessageListener">
  42. <property name="destination" ref="queueDestination"/>
  43. </bean>
  44. <!-- 消息监听容器 -->
  45. <bean id="jmsContainer"        class="org.springframework.jms.listener.DefaultMessageListenerContainer">
  46. <property name="connectionFactory" ref="connectionFactory" />
  47. <property name="destination" ref="queueDestination" />
  48. <property name="messageListener" ref="consumerMessageListener" />
  49. </bean>
  50. <bean id="sessionAwareListenerContainer"
  51. class="org.springframework.jms.listener.DefaultMessageListenerContainer">
  52. <property name="connectionFactory" ref="connectionFactory" />
  53. <property name="destination" ref="sessionAwareQueue" />
  54. <property name="messageListener" ref="consumerSessionAwareMessageListener" />
  55. </bean>
  56. </beans>

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

Java代码  
  1. @RunWith(SpringJUnit4ClassRunner.class)
  2. @ContextConfiguration("/applicationContext.xml")
  3. public class ProducerConsumerTest {
  4. @Autowired
  5. private ProducerService producerService;
  6. @Autowired
  7. @Qualifier("sessionAwareQueue")
  8. private Destination sessionAwareQueue;
  9. @Test
  10. public void testSessionAwareMessageListener() {
  11. producerService.sendMessage(sessionAwareQueue, "测试SessionAwareMessageListener");
  12. }
  13. }

在上述测试代码中,我们通过前面定义好的生产者往我们定义好的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. public class ConsumerListener {
  3. public void handleMessage(String message) {
  4. System.out.println("ConsumerListener通过handleMessage接收到一个纯文本消息,消息内容是:" + message);
  5. }
  6. public void receiveMessage(String message) {
  7. System.out.println("ConsumerListener通过receiveMessage接收到一个纯文本消息,消息内容是:" + message);
  8. }
  9. }

假设我们要把它作为一个消息监听器来监听发送到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"/><!-- 使用MessageListenerAdapter来作为消息监听器 -->
  6. </bean>
  7. <!-- 用于测试消息监听适配器的队列目的地 -->
  8. <bean id="adapterQueue" class="org.apache.activemq.command.ActiveMQQueue">
  9. <constructor-arg>
  10. <value>adapterQueue</value>
  11. </constructor-arg>
  12. </bean>

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

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

Java代码  
  1. package com.tiantian.springintejms.test;
  2. import javax.jms.Destination;
  3. import org.junit.Test;
  4. import org.junit.runner.RunWith;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.beans.factory.annotation.Qualifier;
  7. import org.springframework.test.context.ContextConfiguration;
  8. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
  9. import com.tiantian.springintejms.service.ProducerService;
  10. @RunWith(SpringJUnit4ClassRunner.class)
  11. @ContextConfiguration("/applicationContext.xml")
  12. public class ProducerConsumerTest {
  13. @Autowired
  14. @Qualifier("adapterQueue")
  15. private Destination adapterQueue;
  16. @Test
  17. public void testMessageListenerAdapter() {
  18. producerService.sendMessage(adapterQueue, "测试MessageListenerAdapter");
  19. }
  20. }

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



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



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

当我们用于处理接收到的消息的方法的返回值不为空的时候,Spring会自动将它封装为一个JMS Message,然后自动进行回复。那么这个时候这个回复消息将发送到哪里呢?这主要有两种方式可以指定。

       第一,可以通过发送的Message的setJMSReplyTo方法指定该消息对应的回复消息的目的地。这里我们把我们的生产者发送消息的代码做一下修改,在发送消息之前先指定该消息对应的回复目的地为一个叫responseQueue的队列目的地,具体代码如下所示:

Java代码  
  1. package com.tiantian.springintejms.service.impl;
  2. import javax.jms.Destination;
  3. import javax.jms.JMSException;
  4. import javax.jms.Message;
  5. import javax.jms.Session;
  6. import javax.jms.TextMessage;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.beans.factory.annotation.Qualifier;
  9. import org.springframework.jms.core.JmsTemplate;
  10. import org.springframework.jms.core.MessageCreator;
  11. import org.springframework.stereotype.Component;
  12. import com.tiantian.springintejms.service.ProducerService;
  13. @Component
  14. public class ProducerServiceImpl implements ProducerService {
  15. @Autowired
  16. private JmsTemplate jmsTemplate;
  17. @Autowired
  18. @Qualifier("responseQueue")
  19. private Destination responseDestination;
  20. public void sendMessage(Destination destination, final String message) {
  21. System.out.println("---------------生产者发送消息-----------------");
  22. System.out.println("---------------生产者发了一个消息:" + message);
  23. jmsTemplate.send(destination, new MessageCreator() {
  24. public Message createMessage(Session session) throws JMSException {
  25. TextMessage textMessage = session.createTextMessage(message);
  26. textMessage.setJMSReplyTo(responseDestination);
  27. return textMessage;
  28. }
  29. });
  30. }
  31. }

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

Xml代码  
  1. <!-- 用于测试消息回复的 -->
  2. <bean id="responseQueue" class="org.apache.activemq.command.ActiveMQQueue">
  3. <constructor-arg>
  4. <value>responseQueue</value>
  5. </constructor-arg>
  6. </bean>
  7. <!-- responseQueue对应的监听器 -->
  8. <bean id="responseQueueListener" class="com.tiantian.springintejms.listener.ResponseQueueListener"/>
  9. <!-- responseQueue对应的监听容器 -->
  10. <bean id="responseQueueMessageListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
  11. <property name="connectionFactory" ref="connectionFactory"/>
  12. <property name="destination" ref="responseQueue"/>
  13. <property name="messageListener" ref="responseQueueListener"/>
  14. </bean>

ResponseQueueListener的定义如下所示:

Java代码  
  1. public class ResponseQueueListener implements MessageListener {
  2. public void onMessage(Message message) {
  3. if (message instanceof TextMessage) {
  4. TextMessage textMessage = (TextMessage) message;
  5. try {
  6. System.out.println("接收到发送到responseQueue的一个文本消息,内容是:" + textMessage.getText());
  7. catch (JMSException e) {
  8. e.printStackTrace();
  9. }
  10. }
  11. }
  12. }

接着把我们接收消息的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. @Autowired
  5. private ProducerService producerService;
  6. @Qualifier("adapterQueue")
  7. @Autowired
  8. private Destination adapterQueue;
  9. @Test
  10. public void testMessageListenerAdapter() {
  11. producerService.sendMessage(adapterQueue, "测试MessageListenerAdapter");
  12. }
  13. }

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



        这说明我们的生产者发送消息被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. <bean id="messageListenerAdapterContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
  14. <property name="connectionFactory" ref="connectionFactory"/>
  15. <property name="destination" ref="adapterQueue"/>
  16. <property name="messageListener" ref="messageListenerAdapter"/><!-- 使用MessageListenerAdapter来作为消息监听器 -->
  17. </bean>
  18. !-- 默认的消息回复队列 -->
  19. <bean id="defaultResponseQueue" class="org.apache.activemq.command.ActiveMQQueue">
  20. <constructor-arg>
  21. <value>defaultResponseQueue</value>
  22. </constructor-arg>
  23. </bean>
  24. <!-- defaultResponseQueue对应的监听器 -->
  25. <bean id="defaultResponseQueueListener" class="com.tiantian.springintejms.listener.DefaultResponseQueueListener"/>
  26. <!-- defaultResponseQueue对应的监听容器 -->
  27. <bean id="defaultResponseQueueMessageListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
  28. <property name="connectionFactory" ref="connectionFactory"/>
  29. <property name="destination" ref="defaultResponseQueue"/>
  30. <property name="messageListener" ref="defaultResponseQueueListener"/>
  31. </bean>

DefaultResponseQueueListener的代码如下所示:

Java代码  
  1. package com.tiantian.springintejms.listener;
  2. import javax.jms.JMSException;
  3. import javax.jms.Message;
  4. import javax.jms.MessageListener;
  5. import javax.jms.TextMessage;
  6. public class DefaultResponseQueueListener implements MessageListener {
  7. public void onMessage(Message message) {
  8. if (message instanceof TextMessage) {
  9. TextMessage textMessage = (TextMessage) message;
  10. try {
  11. System.out.println("DefaultResponseQueueListener接收到发送到defaultResponseQueue的一个文本消息,内容是:" + textMessage.getText());
  12. catch (JMSException e) {
  13. e.printStackTrace();
  14. }
  15. }
  16. }
  17. }

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

Java代码  
  1. @Test
  2. public void testMessageListenerAdapter() {
  3. producerService.sendMessage(adapterQueue, "测试MessageListenerAdapter");
  4. }

控制台将输出如下内容:



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

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


Spring学习总结(10)——Spring JMS---三种消息监听器的更多相关文章

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

    原文地址:http://haohaoxuexi.iteye.com/blog/1893676 1.3     消息监听器MessageListener 在Spring整合JMS的应用中我们在定义消息监 ...

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

    *注:别人那复制来的 1.3     消息监听器MessageListener 在Spring整合JMS的应用中我们在定义消息监听器的时候一共可以定义三种类型的消息监听器,分别是MessageList ...

  3. Spring学习之实例化bean的三种方式

    实例化bean的三种方式 构造器实例化bean Person.java public class Person { private String name; private Integer age; ...

  4. Spring 源码学习笔记10——Spring AOP

    Spring 源码学习笔记10--Spring AOP 参考书籍<Spring技术内幕>Spring AOP的实现章节 书有点老,但是里面一些概念还是总结比较到位 源码基于Spring-a ...

  5. Spring学习1:Spring基本特性

    http://longliqiang88.github.io/2015/08/14/Spring%E5%AD%A6%E4%B9%A01%EF%BC%9ASpring%E5%9F%BA%E6%9C%AC ...

  6. Spring框架系列(10) - Spring AOP实现原理详解之AOP代理的创建

    上文我们介绍了Spring AOP原理解析的切面实现过程(将切面类的所有切面方法根据使用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor).本文在此基 ...

  7. SpringBoot 整合 RabbitMQ(包含三种消息确认机制以及消费端限流)

    目录 说明 生产端 消费端 说明 本文 SpringBoot 与 RabbitMQ 进行整合的时候,包含了三种消息的确认模式,如果查询详细的确认模式设置,请阅读:RabbitMQ的三种消息确认模式 同 ...

  8. spring与activemq(三种消息监听方式)

    1.3     消息监听器MessageListener 在Spring整合JMS的应用中我们在定义消息监听器的时候一共可以定义三种类型的消息监听器,分别是MessageListener.Sessio ...

  9. Spring学习(十九)----- Spring的五种事务配置详解

    前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识.通过这次的学习发觉Spring的事务配置只要把思路理清,还是比较好掌握的. ...

随机推荐

  1. Redis封装值ZSet

    /// <summary> /// Sorted Sets是将 Set 中的元素增加了一个权重参数 score,使得集合中的元素能够按 score 进行有序排列 /// 1.带有权重的元素 ...

  2. BZOJ 1146 二分+链剖+线段树+treap

    思路: 恶心的数据结构题-- 首先 我们 链剖 把树 变成序列 再 套一个 区间 第K大就好了-- 复杂度(n*log^4n) //By SiriusRen #include <cstdio&g ...

  3. 程序发布出现: 服务器无法处理请求--->无法生成临时类(result = 1)。 错误CS2001:未能找到源文件“C:\ Windows \ TEMP \ lph54vwf.0.cs”

    服务器上发布的web服务程序出错: 服务器无法处理请求--->无法生成临时类(result = 1).错误CS2001:未能找到源文件“C:\ Windows \ TEMP \ lph54vwf ...

  4. OpenCV中数据转换

    在OpenCV中Mat.CvMat和IplImage类型都可以代表和显示图像.IplImage由CvMat派生,而CvMat由CvArr派生即CvArr -> CvMat -> IplIm ...

  5. Network Stack‎ : HTTP authentication

    HTTP authentication As specified in RFC 2617, HTTP supports authentication using the WWW-Authenticat ...

  6. ubuntu server 网络配置,主机名配置

    一.通过命令ifconfig -a 查看可用网络设备 通过上面的命令,本机可用的网络设备为enp4s0f0 和enp4s0f1 ,不同的系统版本和硬件配置网络设备名可能不一样,所以一定要先确认本机可用 ...

  7. Svn备份与Bandizip压缩批处理程序

    目的:为了定时备份多个svn仓库数据,使用批处理程序进行备份并Bandizip进行压缩保存到指定位置,操作完成后弹出成功提示. 为了完成以上目标,需要了解以下几个方面: 批处理命令 Svn命令 Ban ...

  8. IDEA 热启动,每次更改代码后不用重启服务

    1.ctrl+Shift+Alt+/,选择Registry 2.勾选 compiler.automake.allow.when.app.running(可能不按首字母排序,可以多找找) 3.Setti ...

  9. JavaScript-原型&原型链&原型继承

    JavaScript-原型&原型链&原型继承 JavaScript的原型是一个重要的知识点,很多扩展应用都是从原型出发的.要说原型,我们先简单说一下函数创建过程.上一篇文章用闭包实现类 ...

  10. 【Codeforces Round #459 (Div. 2) C】The Monster

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 左括号看成1 右括号看成-1 设置l,r表示前i个数的和的上下界 遇到 左括号 l和r同时加1 遇到右括号 同时减1 遇到问号 因为 ...