• Spring AMQP 源码RabbitTemplate CachingConnectionFactory


    version: 2.3.7.RELEASE

    以发送消息为代码阅读入口, 消息发送方法 `org.springframework.amqp.rabbit.core.RabbitTemplate#convertAndSend(java.lang.String, java.lang.String, java.lang.Object)`

    创建 `RabbitTemplate` 实例依赖 `org.springframework.amqp.rabbit.connection.CachingConnectionFactory`, 索引首先要创建 `CachingConnectionFactory` 实例

    1. CachingConnectionFactory 实例化

    `CachingConnectionFactory` 的构造方法 `org.springframework.amqp.rabbit.connection.CachingConnectionFactory#CachingConnectionFactory(java.lang.String, int)` 做了如下工作:

      1. 第257行, `newRabbitConnectionFactory()` 创建一个 `com.rabbitmq.client.ConnectionFactory` 实例, 设置  `automaticRecovery` 为 false 然后通过 `AbstractConnectionFactory` 的构造方法赋值给 `org.springframework.amqp.rabbit.connection.AbstractConnectionFactory#rabbitConnectionFactory`

      2. 第264行, 初始化 `org.springframework.amqp.rabbit.connection.CachingConnectionFactory#publisherConnectionFactory`, 用于为生产者创建 connection

      3. 第265行, 初始化父类 `org.springframework.amqp.rabbit.connection.AbstractConnectionFactory#publisherConnectionFactory` 为 `this.publisherConnectionFactory`

     2. 创建 connection

    消息发送调用 `org.springframework.amqp.rabbit.core.RabbitTemplate#doExecute` 方法. 

    在下图第2089行, `connection = ConnectionFactoryUtils.createConnection(connectionFactory, this.usePublisherConnection);` 创建`org.springframework.amqp.rabbit.connection.Connection`

    调用 `org.springframework.amqp.rabbit.connection.CachingConnectionFactory#createConnection`

    调用 `org.springframework.amqp.rabbit.connection.AbstractConnectionFactory#createBareConnection`, 在 `createBareConnection` 方法中看到

      1. `com.rabbitmq.client.Connection rabbitConnection = connect(connectionName);` 创建了一个 rabbitmq connection

      2. 把 `com.rabbitmq.client.Connection` 赋值给 `org.springframework.amqp.rabbit.connection.SimpleConnection#delegate`

      3. `createBareConnection` 方法返回 `org.springframework.amqp.rabbit.connection.SimpleConnection` 实例.

    回到 `org.springframework.amqp.rabbit.connection.CachingConnectionFactory#createConnection` 可以看到:

      1. 把 `org.springframework.amqp.rabbit.connection.SimpleConnection` 赋值给 `org.springframework.amqp.rabbit.connection.CachingConnectionFactory.ChannelCachingConnectionProxy#target`

      2. `createConnection` 方法返回 `org.springframework.amqp.rabbit.connection.CachingConnectionFactory.ChannelCachingConnectionProxy` 实例.

    回到第2089行 `connection = ConnectionFactoryUtils.createConnection(connectionFactory, this.usePublisherConnection);`, 可以确认这里的 `connection` 是一个 `ChannelCachingConnectionProxy` 实例.

     

     3. 创建 channel

    在上图第2095行, `channel = connection.createChannel(false);` 创建 channel

    调用 `org.springframework.amqp.rabbit.connection.CachingConnectionFactory.ChannelCachingConnectionProxy#createChannel`

    调用 `org.springframework.amqp.rabbit.connection.CachingConnectionFactory#getChannel`

    在下图557行, `determineChannelList(connection, transactional);` 返回 `cachedChannelsNonTransactional` 是空的 LinkedList`

    在下图567行, `channel = getCachedChannelProxy(connection, channelList, transactional);` 创建 `org.springframework.amqp.rabbit.connection.ChannelProxy`

    调用 `org.springframework.amqp.rabbit.connection.CachingConnectionFactory#createBareChannel`

    调用 `org.springframework.amqp.rabbit.connection.CachingConnectionFactory#doCreateBareChannel`

    调用 `org.springframework.amqp.rabbit.connection.SimpleConnection#createChannel`, 通过 `Channel channel = this.delegate.createChannel()` 创建 channel, 从上面我们已经知道 ` this.delegate` 是 `com.rabbitmq.client.Connection` 实例

    回到第567行, `org.springframework.amqp.rabbit.connection.CachingConnectionFactory#getCachedChannelProxy` 方法

      1. 通过 Java 动态代理生成 `org.springframework.amqp.rabbit.connection.ChannelProxy` 的代理对象,  `org.springframework.amqp.rabbit.connection.ChannelProxy` 继承 `com.rabbitmq.client.Channel`

      2. 返回代理对象.

      #: 简单理解就是 `ChannelProxy` 代理 `Channel`, 在调用接口方法时改变已有的处理逻辑. 详细处理可以看 `org.springframework.amqp.rabbit.connection.CachingConnectionFactory.CachedChannelInvocationHandler#invoke`, 

      比如重写了 Channel 的 close() 方法, 根据条件把 channle 缓存了起来.

    回到上图第2119行, finally里 `cleanUpAfterAction(channel, invokeScope, resourceHolder, connection);`, 最后会调用 `com.rabbitmq.client.Channel#close()` 方法.

  • 相关阅读:
    正则表达式语法介绍
    关系型数据库和非关系型数据库的简单对比
    lambda函数
    java基础系列--Exception异常处理
    springBoot基础系列--properties配置
    spring基础系列--JavaConfig配置
    java基础系列--Calendar类
    java基础系列--Date类
    一个特殊的List去重问题的解决方案
    Java学习笔记
  • 原文地址:https://www.cnblogs.com/xxoome/p/16013411.html
Copyright © 2020-2023  润新知