### 准备

 

## 目标

了解 Spring AMQP 核心代码

 

## 前置知识

RabbitMQ 入门
 

## 相关资源

 
 
Sample code:<https://github.com/gordonklg/study>,rabbitmq module
 

## 测试代码

gordon.study.rabbitmq.springamqp.Impatient.java

 

### 分析

 

## ConnectionFactory分析

org.springframework.amqp.rabbit.connection.ConnectionFactory 是 Spring AMQP 定义的连接工厂接口,负责创建连接。注意 RabbitMQ client 也有一个同名的连接工厂,这儿用的是 Spring AMQP 定义的。

org.springframework.amqp.rabbit.connection.CachingConnectionFactory 是 ConnectionFactory 的一个实现类。它的属性 com.rabbitmq.client.ConnectionFactory rabbitConnectionFactory 引用了一个真正的 RabbitMQ 连接工厂,一般会在构造函数中被创建出来。后面所有的实际连接都是通过这个 rabbitConnectionFactory 创建的,CachingConnectionFactory 只是管理这些连接。
 
不同于官网示例代码,第16行定义了 URI,表明通过 guest 用户访问 localhost:5672 的 RabbitMQ 服务。原因是我在本机运行时通过 Spring AMQP 自动解析出来的 host 是机器名而不是 localhost,导致 guest 用户没有权限连接,会抛出异常,因此我需要主动将 host 的值设置为 localhost。除了示例代码中用到的通过 URI 指定的方法外,还有以下几种方法:
 
1. 通过可以指定 hostname 的构造函数。适用面窄,不能设置用户名等其它连接工厂属性
 
        ConnectionFactory connectionFactory = new CachingConnectionFactory("localhost");
 
2. 自己创建 com.rabbitmq.client.ConnectionFactory
        com.rabbitmq.client.ConnectionFactory rabbitConnFactory = new com.rabbitmq.client.ConnectionFactory();
        rabbitConnFactory.setHost("localhost");
        rabbitConnFactory.setAutomaticRecoveryEnabled(false);
        ConnectionFactory connectionFactory = new CachingConnectionFactory(rabbitConnFactory);
 
 
 
3. 通过 AbstractConnectionFactory 获取到内部 rabbitConnectionFactory
        AbstractConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.getRabbitConnectionFactory().setHost("localhost");
 
4. 通过 AbstractConnectionFactory 封装的方法间接操作 rabbitConnectionFactory
        AbstractConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setHost("localhost");
 
 
 
 

## AmqpAdmin分析

org.springframework.amqp.core.AmqpAdmin 接口定义了 AMQP 基础管理操作,主要是对各种资源(交换机、队列、绑定)的申明和删除操作。
org.springframework.amqp.rabbit.core.RabbitAdmin 实现了 AmqpAdmin 接口。通过构造函数传入前面创建的 ConnectionFactory 实例,设置到 RabbitAdmin 的 ConnectionFactory connectionFactory 属性中,同时还在构造函数中创建了一个 RabbitTemplate 实例,设置到 RabbitTemplate rabbitTemplate 属性中。
 
declareQueue 方法用来申明队列。org.springframework.amqp.core.Queue 是 Spring AMQP 对队列的封装,其属性与 RabbitMQ Java client 中定义的 Queue 的属性基本一致,new Queue("spring"); 相当于 RabbitMQ Java client 中 channel.queueDeclare("spring", true, false, false, null); 指定的队列特性,即队列是持久化、非排他性、非自动删除的。
 
declareQueue 调用 rabbitTemplate 的 execute(ChannelCallback) 方法,在 ChannelCallback 的回调方法 doInRabbit(com.rabbitmq.client.Channel) 中通过入參 channel 调用 RabbitMQ Java client 提供的 channel.queueDeclare 方法申明队列。代码中有个细节:所有 "amq." 开头的队列会被 Spring AMQP 框架忽略,不会触发 channel.queueDeclare 方法调用。RabbitTemplate 细节下文分析。
 

## AmqpTemplate分析

org.springframework.amqp.core.AmqpTemplate 接口定义了 AMQP 基础操作,主要为同步的消息收发方法。

org.springframework.amqp.rabbit.core.RabbitTemplate 实现了 AmqpTemplate 接口。类似于 RabbitAdmin,RabbitTemplate 也需要引用外部的 ConnectionFactory 用于创建连接。
 
顾名思义,RabbitTemplate 就是 RabbitMQ 收发消息的模板方法,类似于 JdbcTemplate 的设计。所以,RabbitTemplate 要实现创建连接、获取信道、收发消息(等实际操作)、消息格式转换、关闭信道与连接等模板代码。
 
例如,对于 convertAndSend(String routingKey, Object message)方法,首先通过 convertMessageIfNecessary 方法将 Object message 转化为 org.springframework.amqp.core.Message 实例。Message 类是 Spring AMQP 对消息的封装。convertMessageIfNecessary 方法通过获取在 RabbitTemplate 构造函数中创建的 org.springframework.amqp.support.converter.SimpleMessageConverter,调用其 toMessage 方法完成 Message 实例的创建(即消息转化)。
 
接下来,借助 execute(ChannelCallback action, ConnectionFactory connectionFactory) 方法,在 ChannelCallback 接口的匿名实现类的 doInRabbit(Channel) 方法中实现发送消息功能,代码截图如下:

execute(ChannelCallback action, ConnectionFactory connection) 方法与 ChannelCallback 接口合作,成功地将消息发送(等实际操作)与获取连接和信道这两部分代码隔离开。execute 方法中通过传入的 ConnectionFactory 获取连接和信道,ChannelCallback 接口的 doInRabbit(Channel channel) 方法作为回调函数,通过 channel 参数接受 execute 方法中获取的信道,完成消息发送的具体业务。代码实现很简单,在 execute 方法获取到信道 channel 后,调用 action.doInRabbit(channel); 即可。
 
调用栈信息:

 

doSend 方法实现消息发送这个具体操作。本质是通过调用 RabbitMQ Java client 提供的 channel.basicPublish 方法发送消息。

 
业务操作完成后,execute 方法会回收连接和信道资源,整个消息发送模板功能完成。
 
receiveAndConvert 方法实现思路与 convertAndSend 基本一致,调用栈如下:

 
 
 
 
 
 
 
 
 
 
 
 

Spring AMQP 源码分析 01 - Impatient的更多相关文章

  1. Spring AMQP 源码分析 02 - CachingConnectionFactory

    ### 准备 ## 目标 了解 CachingConnectionFactory 在默认缓存模式下的工作原理   ## 前置知识   <Spring AMQP 源码分析 01 - Impatie ...

  2. Spring AMQP 源码分析 08 - XML 配置

    ### 准备 ## 目标 通过 XML 配置文件使用 Spring AMQP ## 前置知识 <Spring AMQP 源码分析 07 - MessageListenerAdapter> ...

  3. Spring AMQP 源码分析 07 - MessageListenerAdapter

    ### 准备 ## 目标 了解 Spring AMQP 如何用 POJO 处理消息 ## 前置知识 <Spring AMQP 源码分析 04 - MessageListener> ## 相 ...

  4. Spring AMQP 源码分析 06 - 手动消息确认

    ### 准备 ## 目标 了解 Spring AMQP 如何手动确认消息已成功消费 ## 前置知识 <Spring AMQP 源码分析 04 - MessageListener> ## 相 ...

  5. Spring AMQP 源码分析 05 - 异常处理

    ### 准备 ## 目标 了解 Spring AMQP Message Listener 如何处理异常 ## 前置知识 <Spring AMQP 源码分析 04 - MessageListene ...

  6. Spring AMQP 源码分析 04 - MessageListener

    ### 准备 ## 目标 了解 Spring AMQP 如何实现异步消息投递(推模式) ## 前置知识 <RabbitMQ入门_05_多线程消费同一队列> ## 相关资源 Quick To ...

  7. Spring AMQP 源码分析 03 - MessageConverter

    ### 准备 ## 目标 了解 Spring AMQP 消息转化实现   ## 相关资源 Quick Tour for the impatient:<http://docs.spring.io/ ...

  8. Spring Ioc源码分析系列--Ioc容器BeanFactoryPostProcessor后置处理器分析

    Spring Ioc源码分析系列--Ioc容器BeanFactoryPostProcessor后置处理器分析 前言 上一篇文章Spring Ioc源码分析系列--Ioc源码入口分析已经介绍到Ioc容器 ...

  9. Spring Security 源码分析(四):Spring Social实现微信社交登录

    社交登录又称作社会化登录(Social Login),是指网站的用户可以使用腾讯QQ.人人网.开心网.新浪微博.搜狐微博.腾讯微博.淘宝.豆瓣.MSN.Google等社会化媒体账号登录该网站. 前言 ...

随机推荐

  1. Genymotion虚拟镜像下载慢或者失败的解决办法

    Genymotion虚拟镜像下载慢或者失败的解决办法 http://files2.genymotion.com/dists/8.0.0/ova/genymotion_vbox86p_8.0_18061 ...

  2. SpringMyBatisDay01

    1.Spring简介 Spring是一个开源轻量级应用开发框架,其目的是用于简化企业级应用程序的开发,降低侵入性Spring提供IOC和AOP功能,可以将组件(就是类)之间的耦合度降至最低,解耦,便于 ...

  3. 摘自(http://www.ruanyifeng.com/blog/2011/07/linux_load_average_explained.html)

    理解Linux系统负荷   作者: 阮一峰 一.查看系统负荷 如果你的电脑很慢,你或许想查看一下,它的工作量是否太大了. 在Linux系统中,我们一般使用uptime命令查看(w命令和top命令也行) ...

  4. 提高php代码质量的36个技巧的摘录

    17.不要直接使用 $_SESSION 变量 简单例子: $_SESSION['username'] = $username; $username = $_SESSION['username'];   ...

  5. Learning to Rank算法介绍:RankNet,LambdaRank,LambdaMart

    之前的博客:http://www.cnblogs.com/bentuwuying/p/6681943.html中简单介绍了Learning to Rank的基本原理,也讲到了Learning to R ...

  6. jquery ui draggable,droppable 学习总结

    刚接触的时候,分不清draggable和droppable的区别,瞎弄了一会,其实很简单,draggable就是“拖”的功能,droppable就是“放”的功能. draggable()是被拖动的元素 ...

  7. 20154312 曾林 ExpFinal CTF Writeup

    0.写在前面 1.不合理的验证方式 2.加密与解密的对抗 3.一个SQL引发的血案 4.管理员的诟病 5.备份信息的泄露 6.svn信息泄露 7.coding 8.平衡权限的威胁 9.文件上传的突破 ...

  8. Azkaban 入门

    需求 实际当中经常有这些场景:每天有一个大任务,这个大任务可以分成A,B,C,D四个小任务,A,B任务之间没有依赖关系,C任务依赖A,B任务的结 果,D任务依赖C任务的结果.一般的做法是,开两个终端同 ...

  9. php 获取随机数的几个方式

    php 获取随机数的几个方式 1.直接获取从min-max的数,例如1-20:$randnum = mt_rand(1, 20); 2.在一个数组里面随机选择一个(验证码的时候需要字母.数字混合的情况 ...

  10. 20145127《java程序设计》第二周学习总结

    本周我又对java程序进行了更进一步的学习.相比与上一周的学习内容的宏观,这一周的所学更加的系统和调理明确. 本周是对java基础语法的学习.首先,我先是认识类型与变量. Java可区分为基本类型和类 ...