交換器和隊列是MQ中high-level層面的構建模塊,應用程序需確保在使用它們的時候就已經存在了,在使用之前需要先聲明它們。以下源碼是基於spring-amqp-1.7.7.RELEASE.jar的源碼分析
- 交換機源碼分析:
public abstract class AbstractExchange extends AbstractDeclarable implements Exchange {
private final String name;
private final boolean durable;
private final boolean autoDelete;
private final Map<String, Object> arguments;
private volatile boolean delayed;
private boolean internal;
public AbstractExchange(String name) {
this(name, true, false);
}
public AbstractExchange(String name, boolean durable, boolean autoDelete) {
this(name, durable, autoDelete, (Map)null);
}
public AbstractExchange(String name, boolean durable, boolean autoDelete, Map<String, Object> arguments) {
this.name = name;
this.durable = durable;
this.autoDelete = autoDelete;
if (arguments != null) {
this.arguments = arguments;
} else {
this.arguments = new HashMap();
}
}
}
FanoutExchange,DirectExchange和TopicExchange等交換機都繼承AbstractExchange,它們交換機的聲明都最終調用得是AbstractExchange的構造方法,各個參數的含義:
- name:交換器(交換機)的名稱;
- durable:設置是否持久化,默認值是true,表示持久化,反之非持久化。持久化可以將交換器存盤,在服務器重啓的時候不會丟失相關信息;
- autoDelete:設置是否自動刪除,默認值false,表示不自動刪除。自動刪除的前提是至少有一個隊列或者交換器與這個交換器綁定,之後所有與這個交換器綁定的隊列或者交換器都與此解綁。不能理解爲:當與此交換器連接的客戶端都斷開時,RabbitMQ會自動刪除本交換器。
- arguments:其他一些結構化參數;
- internal:設置是否是內置的,如果設置爲true,則表示是內置的交換器,客戶端程序無法直接發送消息到這個交換器中,只能通過交換器路由到交換器這種方式。
- 隊列源碼分析:
public class Queue extends AbstractDeclarable {
private final String name;
private final boolean durable;
private final boolean exclusive;
private final boolean autoDelete;
private final Map<String, Object> arguments;
public Queue(String name) {
this(name, true, false, false);
}
public Queue(String name, boolean durable) {
this(name, durable, false, false, (Map)null);
}
public Queue(String name, boolean durable, boolean exclusive, boolean autoDelete) {
this(name, durable, exclusive, autoDelete, (Map)null);
}
public Queue(String name, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments) {
Assert.notNull(name, "'name' cannot be null");
this.name = name;
this.durable = durable;
this.exclusive = exclusive;
this.autoDelete = autoDelete;
this.arguments = arguments;
}
}
隊列有很多重載的構造方法,但他們底層都調用了最下面的那個,參數分析:
- name:隊列名稱;
- durable : 設置是否持久化,默認值爲true表示持久化,持久化的隊列會存盤,在服務器重啓的時候可以保證不丟失相關信息;
- exclusive:設置是否排他,默認不排他。如果一個隊列被聲明爲排他隊列,該隊列僅對首次聲明它的連接可見,並在連接斷開時自動刪除。這裏需要注意三點:1,排他隊列是基於連接可見的,同一個連接的不同信道是可以同時訪問同一連接創建的排他隊列;2,”首次“是指如果一個連接已經聲明瞭一個排他隊列,其他連接是不允許建立同名的排他隊列的,這個與普通隊列不同;3,即使該隊列是持久化的,一旦連接關閉或者客戶端退出,該排他隊列都會被自動刪除,這種隊列適用於一個客戶端同時發送和讀取消息的應用場景。
- autoDelete:設置爲是否自動刪除,默認值false,爲true則設置隊列爲自動刪除。自動刪除的前提是:至少有一個消費者連接到這個隊列,之後所有與這個隊列連接的消費者都斷開時,纔會自動刪除。
- arguments:設置隊列的其他一些參數。
- 隊列的綁定
@Bean
public Binding bindingSelectOrderExchange(Queue queryByOrderIdQueue, DirectExchange directExchange){
/**
* 綁定隊列query.by到指定交換機,並指定路由key
*/
return BindingBuilder.bind(queryByOrderIdQueue).to(directExchange).with("query.by.orderId");
}
源碼如下:
public final class BindingBuilder {
private BindingBuilder() {
}
//1,綁定隊列
public static BindingBuilder.DestinationConfigurer bind(Queue queue) {
return new BindingBuilder.DestinationConfigurer(queue.getName(), DestinationType.QUEUE);
}
public static final class DirectExchangeRoutingKeyConfigurer extends BindingBuilder.AbstractRoutingKeyConfigurer<DirectExchange> {
private DirectExchangeRoutingKeyConfigurer(BindingBuilder.DestinationConfigurer destination, DirectExchange exchange) {
super(destination, exchange.getName(), null);
}
//2,指定路由key
public Binding with(String routingKey) {
return new Binding(this.destination.name, this.destination.type, this.exchange, routingKey, Collections.emptyMap());
}
public Binding with(Enum<?> routingKeyEnum) {
return new Binding(this.destination.name, this.destination.type, this.exchange, routingKeyEnum.toString(), Collections.emptyMap());
}
public Binding withQueueName() {
return new Binding(this.destination.name, this.destination.type, this.exchange, this.destination.name, Collections.emptyMap());
}
}
public static final class DestinationConfigurer {
protected final String name;
protected final DestinationType type;
private DestinationConfigurer(String name, DestinationType type) {
this.name = name;
this.type = type;
}
public Binding to(FanoutExchange exchange) {
return new Binding(this.name, this.type, exchange.getName(), "", new HashMap());
}
public BindingBuilder.HeadersExchangeMapConfigurer to(HeadersExchange exchange) {
return new BindingBuilder.HeadersExchangeMapConfigurer(this, exchange);
}
//3,綁定到DirectExchange交換機
public BindingBuilder.DirectExchangeRoutingKeyConfigurer to(DirectExchange exchange) {
return new BindingBuilder.DirectExchangeRoutingKeyConfigurer(this, exchange);
}
public BindingBuilder.TopicExchangeRoutingKeyConfigurer to(TopicExchange exchange) {
return new BindingBuilder.TopicExchangeRoutingKeyConfigurer(this, exchange);
}
public BindingBuilder.GenericExchangeRoutingKeyConfigurer to(Exchange exchange) {
return new BindingBuilder.GenericExchangeRoutingKeyConfigurer(this, exchange);
}
}
}