1. RabbitTemplate#convertAndSend
rabbitmq的发送可以通过AmqpTemplate接口实现,AmqpTemplate接口下重载了许多send和convertAndSend方法。send用于发送Message格式的数据,convertAndSend方法先将对象转化成Message数据后进行发送。
从前面的配置类中可以看到,默认使用的AmqpTemplate是RabbitTemplate,以RabbitTemplate#convertAndSend(String, String, Object)
@Override
public void convertAndSend(String exchange, String routingKey, final Object object, CorrelationData correlationData)
throws AmqpException {
send(exchange, routingKey, convertMessageIfNecessary(object), correlationData);
}
然后委托MessageConverter类将对象转化成Message数据
protected Message convertMessageIfNecessary(final Object object) {
if (object instanceof Message) {
return (Message) object;
}
return getRequiredMessageConverter().toMessage(object, new MessageProperties());
}
2. SimpleMessageConverter#createMessage
MessageConverter接口只有两个方法,分别用于将对象转换成Message和将Message还原回对象。
RabbitTemplate#messageConvert的默认值是SimpleMessageConverter,其toMessage方法继承自父类AbstractMessageConverter,具体逻辑如下,其核心逻辑在于SimpleMessageConverter#createMessage中。
@Override
public final Message toMessage(Object object, MessageProperties messageProperties)
throws MessageConversionException {
if (messageProperties == null) {
messageProperties = new MessageProperties();
}
Message message = createMessage(object, messageProperties);
messageProperties = message.getMessageProperties();
if (this.createMessageIds && messageProperties.getMessageId() == null) {
messageProperties.setMessageId(UUID.randomUUID().toString());
}
return message;
}
@Override
protected Message createMessage(Object object, MessageProperties messageProperties) throws MessageConversionException {
byte[] bytes = null;
if (object instanceof byte[]) {
bytes = (byte[]) object;
messageProperties.setContentType(MessageProperties.CONTENT_TYPE_BYTES);
}
else if (object instanceof String) {
try {
bytes = ((String) object).getBytes(this.defaultCharset);
}
catch (UnsupportedEncodingException e) {
throw new MessageConversionException(
"failed to convert to Message content", e);
}
messageProperties.setContentType(MessageProperties.CONTENT_TYPE_TEXT_PLAIN);
messageProperties.setContentEncoding(this.defaultCharset);
}
else if (object instanceof Serializable) {
try {
bytes = SerializationUtils.serialize(object);
}
catch (IllegalArgumentException e) {
throw new MessageConversionException(
"failed to convert to serialized Message content", e);
}
messageProperties.setContentType(MessageProperties.CONTENT_TYPE_SERIALIZED_OBJECT);
}
if (bytes != null) {
messageProperties.setContentLength(bytes.length);
return new Message(bytes, messageProperties);
}
throw new IllegalArgumentException(getClass().getSimpleName()
+ " only supports String, byte[] and Serializable payloads, received: " + object.getClass().getName());
}
SimpleMessageConverter#toMessage方法通过new Message(bytes, messageProperties)生成返回的对象。因此在转化对象时需要考虑的是如何将对象转化成字节数组以及对应的contentType。
转换成字节数组的方式根据对象类型有4种场景:
(1)字节数组:不需要转化
(2)字符串:直接使用String#getBytes
(3)可序列化对象:进行序列化
(4)其它:抛出异常
3. RabbitTemplate#send
RabbitTemplate内所有重载的send和convertAndSend方法都通过调用public void send(final String exchange, final String routingKey, final Message message, final CorrelationData correlationData) throws AmqpException
来进行消息的发送,而这个方法有委托execute方法处理逻辑。