欢迎支持笔者新作:《深入理解Kafka:核心设计与实践原理》和《RabbitMQ实战指南》,同时欢迎关注笔者的微信公众号:朱小厮的博客。
欢迎跳转到本文的原文链接:https://honeypps.com/mq/rabbitmq-client-source-code-of-amqpimpl/
AMQPImpl类包括AMQP接口(public class AMQImpl implements AMQP)主要囊括了AMQP协议中的通信帧的类别。
这里以Connection.Start帧做一个例子。
public static class Connection {
public static final int INDEX = 10;
public static class Start
extends Method
implements com.rabbitmq.client.AMQP.Connection.Start
{
public static final int INDEX = 10;
private final int versionMajor;
private final int versionMinor;
private final Map<String,Object> serverProperties;
private final LongString mechanisms;
private final LongString locales;
....//下面省略很多代码。。。
可以看到Start类是Connection类的内部静态子类,表示此Start类为Connection.Start,而且Start类是继承Method方法的,包括接下来所有的AMQP协议帧都是继承这个Method方法,Method可以看成用来区分AMQP协议帧的类型。
Method类是一个抽象类(Base class for AMQP method objects, specialized by autogenerated code in AMQP.java),我们来看下Method类的代码:
public abstract class Method implements com.rabbitmq.client.Method {
/** {@inheritDoc} */
public abstract int protocolClassId(); /* properly an unsigned short */
/** {@inheritDoc} */
public abstract int protocolMethodId(); /* properly an unsigned short */
/** {@inheritDoc} */
public abstract String protocolMethodName();
/**
* Tell if content is present.
* @return true if the wire-protocol for this method should involve a content header and body,
* or false if it should just involve a single method frame.
*/
public abstract boolean hasContent();
/**
* Visitor support (double-dispatch mechanism).
* @param visitor the visitor object
* @return the result of the "visit" operation
* @throws IOException if an error is encountered
*/
public abstract Object visit(MethodVisitor visitor) throws IOException;
/**
* Private API - Autogenerated writer for this method.
* @param writer interface to an object to write the method arguments
* @throws IOException if an error is encountered
*/
public abstract void writeArgumentsTo(MethodArgumentWriter writer) throws IOException;
/**
* Public API - debugging utility
* @param buffer the buffer to append debug data to
*/
public void appendArgumentDebugStringTo(StringBuilder buffer) {
buffer.append("(?)");
}
@Override public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("#method<").append(protocolMethodName()).append(">");
this.appendArgumentDebugStringTo(sb);
return sb.toString();
}
public Frame toFrame(int channelNumber) throws IOException {
Frame frame = new Frame(AMQP.FRAME_METHOD, channelNumber);
DataOutputStream bodyOut = frame.getOutputStream();
bodyOut.writeShort(protocolClassId());
bodyOut.writeShort(protocolMethodId());
MethodArgumentWriter argWriter = new MethodArgumentWriter(new ValueWriter(bodyOut));
writeArgumentsTo(argWriter);
argWriter.flush();
return frame;
}
}
代码不长。挑几个解释下。
protocolClassId()和protocolMethodId():每一个Method(Connection.Start/.StartOk, Connection.Tune/.TuneOk等等)都包含classId和methodId,可以参考下图:
protocolMethodName()返回本Method的名称,比如Connection.Start的就是:
public String protocolMethodName() { return "connection.start";}
boolean hasContent()用来区分这个Method之后是否有Content-Body,比如Connection.Start的为:
public boolean hasContent() { return false; }
又比如Basic.Publish的为:
public boolean hasContent() { return true; }
好了,这里可以回来接着讲AMQPImpl了。
下面是一张表,用来涵盖AQMP协议各个种类的Method以及其一些属性,看完这张表就看完了AMQPImpl的全部。
Method-Name | classId | methodId | hasContent |
---|---|---|---|
Connection.Start | 10 | 10 | false |
Connection.StartOk | 10 | 11 | false |
Connection.Secure | 10 | 20 | false |
Connection.SecureOk | 10 | 21 | false |
Connection.Tune | 10 | 30 | false |
Connection.TuneOk | 10 | 31 | false |
Connection.Open | 10 | 40 | false |
Connection.OpenOk | 10 | 41 | false |
Connection.Close | 10 | 50 | false |
Connection.CloseOk | 10 | 51 | false |
Connection.Blocked | 10 | 60 | false |
Connection.Unblocked | 10 | 61 | false |
Channel.Open | 20 | 10 | false |
Channel.OpenOk | 20 | 11 | false |
Channel.Flow | 20 | 20 | false |
Channel.FlowOk | 20 | 21 | false |
Channel.Close | 20 | 40 | false |
Channel.CloseOk | 20 | 41 | false |
Access.Request | 30 | 10 | false |
Access.RequestOk | 30 | 11 | false |
Exchange.Declare | 40 | 10 | false |
Exchange.DeclareOk | 40 | 11 | false |
Exchange.Delete | 40 | 20 | false |
Exchange.DeleteOk | 40 | 21 | false |
Exchange.Bind | 40 | 30 | false |
Exchange.BindOk | 40 | 31 | false |
Exchange.Unbind | 40 | 40 | false |
Exchange.UnbindOk | 40 | 51 | false |
Queue.Declare | 50 | 10 | false |
Queue.DeclareOk | 50 | 11 | false |
Queue.Bind | 50 | 20 | false |
Queue.BindOk | 50 | 21 | false |
Queue.Purge | 50 | 30 | false |
Queue.PurgeOk | 50 | 31 | false |
Queue.Delete | 50 | 40 | false |
Queue.DeleteOk | 50 | 41 | false |
Queue.Unbind | 50 | 50 | false |
Queue.UnbindOk | 50 | 51 | false |
Basic.Qos | 60 | 10 | false |
Basic.QosOk | 60 | 11 | false |
Basic.Consume | 60 | 20 | false |
Basic.ConsumeOk | 60 | 21 | false |
Basic.Cancel | 60 | 30 | false |
Basic.CancelOk | 60 | 31 | false |
Basic.Publish | 60 | 40 | true |
Basic.Return | 60 | 50 | true |
Basic.Deliver | 60 | 60 | true |
Basic.Get | 60 | 70 | false |
Basic.GetOk | 60 | 71 | true |
Basic.GetEmpty | 60 | 72 | false |
Basic.Ack | 60 | 80 | false |
Basic.Reject | 60 | 90 | false |
Basic.RecoverAsync | 60 | 100 | false |
Basic.Recover | 60 | 110 | false |
Basic.RecoverOk | 60 | 111 | false |
Basic.Nack | 60 | 120 | false |
Tx.Select | 90 | 10 | false |
Tx.SelectOk | 90 | 11 | false |
Tx.Commit | 90 | 20 | false |
Tx.CommitOk | 90 | 21 | false |
Tx.Rollback | 90 | 30 | false |
Tx.RollbackOk | 90 | 31 | false |
Confirm.Select | 85 | 10 | false |
Confirm.SelectOk | 85 | 11 | false |
附:本系列全集
- [Conclusion]RabbitMQ-客户端源码之总结
- [一]RabbitMQ-客户端源码之ConnectionFactory
- [二]RabbitMQ-客户端源码之AMQConnection
- [三]RabbitMQ-客户端源码之ChannelManager
- [四]RabbitMQ-客户端源码之Frame
- [五]RabbitMQ-客户端源码之AMQChannel
- [六]RabbitMQ-客户端源码之AMQCommand
- [七]RabbitMQ-客户端源码之AMQPImpl+Method
- [八]RabbitMQ-客户端源码之ChannelN
- [九]RabbitMQ-客户端源码之Consumer
欢迎跳转到本文的原文链接:https://honeypps.com/mq/rabbitmq-client-source-code-of-amqpimpl/
欢迎支持笔者新作:《深入理解Kafka:核心设计与实践原理》和《RabbitMQ实战指南》,同时欢迎关注笔者的微信公众号:朱小厮的博客。