Spring RabbitMQ 源碼分析

目錄

 

一、知識點

1、RabbitListenerEndpoint :

2、RabbitListenerContainerFactory

二、開始

1、HandlerMethod

2、ChannelAwareMessageListener 

3、SimpleMessageListenerContainer

4、RabbitListenerAnnotationBeanPostProcessor


一、知識點

1、RabbitListenerEndpoint :

Endpoint爲終端,像電腦、手機都是終端,他們都可以接受外部信息並響應,如手機來短信了就有提示。這裏也用了終端的概念,例如:被@RabbitListener註解修飾方法也有終端的特點 可以接受外部信息並響應。

public interface RabbitListenerEndpoint {

   /**
    * the id of this endpoint
    */
   String getId();

   /**
    * the group of this endpoint or null if not in a group.
    */
   String getGroup();

   /**
    *the concurrency of this endpoint.
    */
   String getConcurrency();

   /**
    * Override of the default autoStartup property.
    */
   Boolean getAutoStartup();

   /**
    * Setup the specified message listener container with the model
    * defined by this endpoint.
    */
   void setupListenerContainer(MessageListenerContainer listenerContainer);

}

這裏的終端有很多種,剛纔說到 『被@RabbitListener註解修飾方法也是終端』 就是 MethodRabbitListenerEnpoint 方法終端。

接口方法中 void setupListenerContainer(MessageListenerContainer listenerContainer) 方法,中的MessageListenerContainer就是用來接收並處理消息的。

 

在抽象類中AbstractRabbitListenerEndpoint對setupListenerContainer方法進了實現:
    @Override
    public void setupListenerContainer(MessageListenerContainer listenerContainer) { 
            ……
        setupMessageListener(listenerContainer);
    }
    private void setupMessageListener(MessageListenerContainer container) {
        //MessageListenerContainer爲容器,容器是要裝東西的,這裏顯然是裝MessageListener。
        //createMessageListener(container)爲抽象方法,用於子類覆蓋。
        MessageListener messageListener = createMessageListener(container);
        container.setupMessageListener(messageListener);
        
    }
    
   

子類MethodRabbitListenerEndpoint中覆蓋了createMessageListener。


    @Override
    protected MessagingMessageListenerAdapter createMessageListener(MessageListenerContainer container) {
        //創建 messageListener
        MessagingMessageListenerAdapter messageListener = createMessageListenerInstance();
        //        
        messageListener.setHandlerMethod(configureListenerAdapter(messageListener));
        
        return messageListener;

    }

    protected MessagingMessageListenerAdapter createMessageListenerInstance() {
        return new MessagingMessageListenerAdapter(this.bean, this.method, this.returnExceptions, this.errorHandler);
    }

    protected HandlerAdapter configureListenerAdapter(MessagingMessageListenerAdapter messageListener) {
        InvocableHandlerMethod invocableHandlerMethod =
                this.messageHandlerMethodFactory.createInvocableHandlerMethod(getBean(), getMethod());
        return new HandlerAdapter(invocableHandlerMethod);
    }
    
    


2、RabbitListenerContainerFactory

RabbitListenerContainerFactory爲:rabbit 監聽器容器工廠。既然爲 監聽器容器工廠 那一定是生產監聽器容器。

監聽器容器工廠:

public interface RabbitListenerContainerFactory<C extends MessageListenerContainer> {

   /**
    * Create a {@link MessageListenerContainer} for the given {@link RabbitListenerEndpoint}.
    */
   C createListenerContainer(RabbitListenerEndpoint endpoint);

}

監聽器容器: 

public interface MessageListenerContainer extends SmartLifecycle {

	/**
	 * Setup the message listener to use. Throws an {@link IllegalArgumentException}
	 * if that message listener type is not supported.
	 */
	void setupMessageListener(Object messageListener);

	/**
	 * @return the {@link MessageConverter} that can be used to
	 * convert {@link org.springframework.amqp.core.Message}, if any.
	 */
	MessageConverter getMessageConverter();

}

 監聽器容器工廠:

 在其抽象子類AbstractRabbitListenerContainerFactory中對 createListenerContainer 方法已做了實現。

我常用的是其子類SimpleRabbitListenerContainerFactory

public class SimpleRabbitListenerContainerFactory
		extends AbstractRabbitListenerContainerFactory<SimpleMessageListenerContainer> {}

SimpleRabbitListenerContainerFactory工廠生產的是SimpleMessageListenerContainer

public class AbstractRabbitListenerContainerFactory<C extends AbstractMessageListenerContainer>    implements RabbitListenerContainerFactory<C>{

    //在使用SimpleRabbitListenerContainerFactory時,下面的 C 就是 SimpleMessageListenerContainer
	@Override
	public C createListenerContainer(RabbitListenerEndpoint endpoint) {
		//創建SimpleMessageListenerContainer
		C instance = createContainerInstance();

		if (this.connectionFactory != null) {
			instance.setConnectionFactory(this.connectionFactory);
		}
		if (this.errorHandler != null) {
			instance.setErrorHandler(this.errorHandler);
		}
		if (this.messageConverter != null) {
			instance.setMessageConverter(this.messageConverter);
		}

		……

	        //setupListenerContainer方法參數爲 MessageListenerContainer類型,
              //SimpleMessageListenerContainer是MessageListenerContainer的子類。
		endpoint.setupListenerContainer(instance);
		if (instance.getMessageListener() instanceof AbstractAdaptableMessageListener) {
			AbstractAdaptableMessageListener messageListener = (AbstractAdaptableMessageListener) instance
					.getMessageListener();
			if (this.beforeSendReplyPostProcessors != null) {
				messageListener.setBeforeSendReplyPostProcessors(this.beforeSendReplyPostProcessors);
			}
			if (this.retryTemplate != null) {
				messageListener.setRetryTemplate(this.retryTemplate);
				if (this.recoveryCallback != null) {
					messageListener.setRecoveryCallback(this.recoveryCallback);
				}
			}
		}
		initializeContainer(instance, endpoint);

		return instance;
	}
}

 

二、開始

 

1、HandlerMethod

  在被@RabbitListener標註的方法。該方法會被封裝成HanderMethod。

HandlerMethod{
  private final Object bean;
  private final Method method;

  public HandlerMethod(Object bean, Method method) {
      this.bean = bean;
      this.method = method;
  }
}

我們常用其子類InvocableHandlerMethod。該類提供一個Object invoke(Message<?> message, Object... providedArgs) 方法,
 可以通過該invoke方法調用handlerMethod 中的method:method.invoke(bean,args)

HandlerAdapter稱爲hander適配器,該適配器中有InvocableHandlerMethod、DelegatingInvocableHandler這兩個hander方法。注:InvocableHandlerMethod上文剛說過。

public class HandlerAdapter {
  private final InvocableHandlerMethod invokerHandlerMethod;
  private final DelegatingInvocableHandler delegatingHandler;

  public Object invoke(Message<?> message, Object... providedArgs) throws Exception                
  {
      if (this.invokerHandlerMethod != null) {
          //InvocableHandlerMethod不爲null,就調用invokerHandlerMethod.invoke方法。
          return this.invokerHandlerMethod.invoke(message, providedArgs);

      }else if (this.delegatingHandler.hasDefaultHandler()) {
            //……
      }else {
            //……
      }
   }
}

這裏可以簡單的理解調用HandlerAdapter.invoke方法可以間接調用@RabbitListener修飾的方法。

 

2、ChannelAwareMessageListener 

消費端接收到mq的消息會調用ChannelAwareMessageListener 接口中的onMessage方法。

public interface ChannelAwareMessageListener {

	/**
	 * 回調函數處理接受的消息
	 */
	void onMessage(Message message, Channel channel) throws Exception;

}

下面要說的是其子類:MessagingMessageListenerAdapter

public class MessagingMessageListenerAdapter extends AbstractAdaptableMessageListener {

	private HandlerAdapter handlerMethod;
	
	
	@Override
	public void onMessage(org.springframework.amqp.core.Message amqpMessage, Channel channel) throws Exception {
		
		//ChannelAwareMessageListener.onMessage()方法中的message是org.springframework.amqp.core.Message類型。
        //這裏轉換成org.springframework.messaging.Message類型。
		Message<?> message = toMessagingMessage(amqpMessage);
		try {
			Object result = invokeHandler(amqpMessage, channel, message);
			if (result != null) {
				handleResult(result, amqpMessage, channel, message);
			}
		}
		catch () {}
	}
	
	private Object invokeHandler(org.springframework.amqp.core.Message amqpMessage, Channel channel,
			Message<?> message) {
		try {
			return this.handlerMethod.invoke(message, amqpMessage, channel);
		}
		catch () {}
		
	}
	
}

onMessage->invokehandler->this.handlerMethod.invoke 。this.handlerMethod爲 HandlerAdapter類型。上面剛說完:調用HandlerAdapter.invoke方法可以間接調用@RabbitListener修飾的方法

現在我們就已經梳洗清楚從onMessage到調用被@RabbitListener修飾的方法的整個流程

 

3、SimpleMessageListenerContainer

 

SimpleMessageListenerContainer 中有一個內部類AsyncMessageProcessingConsumer :

  //當終端接受到信息時,一個線程會執行該run方法。
    private final class AsyncMessageProcessingConsumer implements Runnable {
        @Override
        public void run() {
            //這個 while 可以無限的循環,
            while (isActive(this.consumer) || this.consumer.hasDelivery() || !this.consumer.cancelled()) {
                boolean receivedOk = receiveAndExecute(this.consumer); // At least one message received
            }
        }
    }

run方法中調用了receiveAndExecute方法,方法名直譯:接受並執行。

SimpleMessageListenerContainer {


     //接受並執行
    private boolean receiveAndExecute(final BlockingQueueConsumer consumer) throws Throwable {

       //do接受並執行
        return doReceiveAndExecute(consumer);
    }
     //do接受並執行
    private boolean doReceiveAndExecute(BlockingQueueConsumer consumer) throws Throwable {

        Channel channel = consumer.getChannel();
        for (int i = 0; i < this.txSize; i++) {//txSize爲一次事務接受的消息個數
            //讀取消息,這裏阻塞的,但是有一個超時時間。
            Message message = consumer.nextMessage(this.receiveTimeout);
            if (message == null) {//阻塞超時
				break;
			}
            try {
                executeListener(channel, message);//消息接收已完成,現在開始處理消息。
            }
            catch (Exception e) {}
        }
        return consumer.commitIfNecessary(isChannelLocallyTransacted());
    }
        
    
    //處理消息開始。該方法在其父類中
    protected void executeListener(Channel channel, Message messageIn) throws Exception {
        try {
            Message message = messageIn;
            if (……) {
                //批處理信息,這個不研究
            }else {
                invokeListener(channel, message);
            }
        }catch (Exception ex) {}
    }
    //在其父類中
    protected void invokeListener(Channel channel, Message message) throws Exception {
        //這裏this.proxy.invokeListener最終會調用actualInvokeListener方法。
        this.proxy.invokeListener(channel, message);
    }
    //在其父類中
    protected void actualInvokeListener(Channel channel, Message message) throws Exception {
        Object listener = getMessageListener();
        if (listener instanceof ChannelAwareMessageListener) {
            doInvokeListener((ChannelAwareMessageListener) listener, channel, message);
        }
        else if (listener instanceof MessageListener) {
            //……
            doInvokeListener((MessageListener) listener, message)
        }else{
            //……
        }
        
    }    

    protected void doInvokeListener(ChannelAwareMessageListener listener, Channel channel, Message message)
            throws Exception {
            Channel channelToUse = channel;
            try {
                listener.onMessage(message, channelToUse);
            }
            catch (Exception e) {
                throw wrapToListenerExecutionFailedExceptionIfNeeded(e, message);
            }

    }
}

在doInvokeListener方中最終調用了onMessage方法。

到這我知道了SimpleMessageListenerContainer內部類AsyncMessageProcessingConsumer被放入線程池中運行,是誰把AsyncMessageProcessingConsumer放入線程池中的呢?


4、RabbitListenerAnnotationBeanPostProcessor

RabbitListenerAnnotationBeanPostProcessor 聽名得意:@RabbitListener註解的後置處理器。

public class RabbitListenerAnnotationBeanPostProcessor implements BeanPostProcessor,SmartInitializingSingleton {

    //對接口BeanPostProcessor的實現。
    @Override
    public Object postProcessAfterInitialization(final Object bean, final String beanName) throws BeansException {
        Class<?> targetClass = AopUtils.getTargetClass(bean);
        final TypeMetadata metadata = this.typeCache.computeIfAbsent(targetClass, this::buildMetadata);
        for (ListenerMethod lm : metadata.listenerMethods) {//獲取被@RabbitListener修飾的方法。
            for (RabbitListener rabbitListener : lm.annotations) {//獲取方法上的@RabbitListener註解。
                //處理Amqp監聽:
                //有這三個參數就以實現監聽隊列並調用方法。參數:rabbitListener爲我們的方法上@RabbitListener註解。參數method和bean可以能過反射的方式調用我們的方法。
                processAmqpListener(rabbitListener, lm.method, bean, beanName);
            }
        }
        return bean;
    }
    
    //處理Amqp監聽
    protected void processAmqpListener(RabbitListener rabbitListener, Method method, Object bean, String beanName) {
        Method methodToUse = checkProxy(method, bean);
        
        //Endpoint爲終端,像電腦、手機都是終端,他們都可以接受外部信息並響應,如手機來短信了就有提示。
        //這裏也用了終端的概念,被@RabbitListener註解修飾方法也有終端的特點可以接受外部信息並響應。
        //MethodRabbitListenerEndpoint名子也很形象,叫方法監聽終端。
        MethodRabbitListenerEndpoint endpoint = new MethodRabbitListenerEndpoint();
        endpoint.setMethod(methodToUse);//終端接收到信息時,會調用 methodToUse
        processListener(endpoint, rabbitListener, bean, methodToUse, beanName);
    }
    //註冊員
    private final RabbitListenerEndpointRegistrar registrar = new RabbitListenerEndpointRegistrar();
    
    protected void processListener(MethodRabbitListenerEndpoint endpoint, RabbitListener rabbitListener, Object bean,
            Object adminTarget, String beanName) {
        //下面是爲終端注入一些屬性
        endpoint.setBean(bean);
        endpoint.setMessageHandlerMethodFactory(this.messageHandlerMethodFactory);
        endpoint.setId(getEndpointId(rabbitListener));
        endpoint.setQueueNames(resolveQueues(rabbitListener));
        endpoint.setConcurrency(resolveExpressionAsStringOrInteger(rabbitListener.concurrency(), "concurrency"));
        endpoint.setBeanFactory(this.beanFactory);
        endpoint.setReturnExceptions(resolveExpressionAsBoolean(rabbitListener.returnExceptions()));

        ……

        RabbitListenerContainerFactory<?> factory = null;
		String containerFactoryBeanName = resolve(rabbitListener.containerFactory());
		if (StringUtils.hasText(containerFactoryBeanName)) {
			Assert.state(this.beanFactory != null, "BeanFactory must be set to obtain container factory by bean name");
			try {
				factory = this.beanFactory.getBean(containerFactoryBeanName, RabbitListenerContainerFactory.class);
			}
			catch (NoSuchBeanDefinitionException ex) {
				throw new BeanInitializationException("Could not register rabbit listener endpoint on [" +
						adminTarget + "] for bean " + beanName + ", no " + RabbitListenerContainerFactory.class.getSimpleName() + " with id '" +
						containerFactoryBeanName + "' was found in the application context", ex);
			}
		}
        //終端準備完成後,還要將終端進行註冊。    
        //註冊員將終端註冊到註冊處
        this.registrar.registerEndpoint(endpoint, factory);
    }
    
    
    

    
    //對SmartInitializingSingleton的實現,該方法在bean的後置處理BeanPostProcessor之後調用。
    @Override
    public void afterSingletonsInstantiated() {
        this.registrar.setBeanFactory(this.beanFactory);

        if (this.containerFactoryBeanName != null) {
            //this.containerFactoryBeanName爲“rabbitListenerContainerFactory”
            this.registrar.setContainerFactoryBeanName(this.containerFactoryBeanName);
        }

        // Actually register all listeners
        this.registrar.afterPropertiesSet();

    }

}

    

RabbitListenerEndpointRegistrar :rabbit 監聽器註冊員

//終端註冊員
public class RabbitListenerEndpointRegistrar   implements  InitializingBean{

	private RabbitListenerEndpointRegistry endpointRegistry;//終端註冊處
    //終端描述器集合
	private final List<AmqpListenerEndpointDescriptor> endpointDescriptors =
			new ArrayList<AmqpListenerEndpointDescriptor>();

    //註冊員將終端註冊到註冊處
	public void registerEndpoint(RabbitListenerEndpoint endpoint, RabbitListenerContainerFactory<?> factory) {
		
		//將 endpoint和 factory 封裝成 終端描述器
		AmqpListenerEndpointDescriptor descriptor = new AmqpListenerEndpointDescriptor(endpoint, factory);
		synchronized (this.endpointDescriptors) {
			if (this.startImmediately) { //馬下注冊
				 //將 終端註冊到 終端註冊處
				this.endpointRegistry.registerListenerContainer(descriptor.endpoint,
						resolveContainerFactory(descriptor), true);
			}
			else {//afterPropertiesSet()方法中統一註冊
                                   //放入終端描述器集合
				this.endpointDescriptors.add(descriptor);
			}
		}
	}

     //InitializingBean接口的實現
     @Override
    public void afterPropertiesSet() {
        //統一註冊
        registerAllEndpoints();
    }
    //統一註冊
    protected void registerAllEndpoints() {
        synchronized (this.endpointDescriptors) {
            for (AmqpListenerEndpointDescriptor descriptor : this.endpointDescriptors) {
                this.endpointRegistry.registerListenerContainer(
                        descriptor.endpoint, resolveContainerFactory(descriptor));
            }
        }
    }
    




}

 

RabbitListenerEndpointRegistry:註冊處

public class RabbitListenerEndpointRegistry  implements SmartLifecycle{

	private final Map<String, MessageListenerContainer> listenerContainers =
			new ConcurrentHashMap<String, MessageListenerContainer>();
	//註冊終端
	public void registerListenerContainer(RabbitListenerEndpoint endpoint, RabbitListenerContainerFactory<?> factory,
				boolean startImmediately) {

		String id = endpoint.getId();
		synchronized (this.listenerContainers) {
			//創建 listenerContainer
			MessageListenerContainer container = createListenerContainer(endpoint, factory);
			this.listenerContainers.put(id, container);
			……

			if (startImmediately) {
				startIfNecessary(container);
			}
		}
	}

	    protected MessageListenerContainer createListenerContainer(RabbitListenerEndpoint endpoint,
            RabbitListenerContainerFactory<?> factory) {
        //調用RabbitListener容器工廠的createListenerContainer方法獲取RabbitListener容器
        MessageListenerContainer listenerContainer = factory.createListenerContainer(endpoint);

        return listenerContainer;
    }

    //start 是對 smartLifecycle 接口的實現,由 spring 容器調用
       //上面的的代碼中已經創建了listenerContainer 並放入了listenerContainers集合中,現在要將集合中的 listenerContainer放入線程池中。
    	@Override
	public void start() {
        //遍歷listenerContainers集合
		for (MessageListenerContainer listenerContainer : getListenerContainers()) {
			startIfNecessary(listenerContainer);
		}
	}
    //調用集合中的listenerContainer的 start 方法。
      private void startIfNecessary(MessageListenerContainer listenerContainer) {
		if (this.contextRefreshed || listenerContainer.isAutoStartup()) {
			listenerContainer.start();
		}
	}

}

分析了RabbitListenerAnnotationBeanPostProcessor:@RabbitListener註解的後置處理器 。從讀取被@RabbitListener修飾的方法 => 創建 endpoint =>創建MessageListenerContainer並放入集合中=>遍歷集合中的MessageListenerContainer並調用 start方法。

 

MessageListenerContainer中的 start 方法做了什麼?

其子類 SimpleMessageListenerContainer是我們學習的重點

public interface MessageListenerContainer extends SmartLifecycle {

	/**
	 * Setup the message listener to use. Throws an {@link IllegalArgumentException}
	 * if that message listener type is not supported.
	 */
	void setupMessageListener(Object messageListener);

	/**
	 * @return the {@link MessageConverter} that can be used to
	 * convert {@link org.springframework.amqp.core.Message}, if any.
	 */
	MessageConverter getMessageConverter();

}

start 方法在其抽象子類 AbstractMessageListenerContainer 中實現了:

    //MessageListenerContainer 同樣也繼承了 SmartLifecycle接口,SmartLifecycle中的方法是由 Spring 容器調用的,這裏我們手動調用了 start 方法,這意味這 start 會被調用兩次。
    @Override
	public void start() {
		if (isRunning()) {//第二調用時會直接 return。
			return;
		}
		
		try {
			doStart();
		}
		catch (Exception ex) {
		}
	}

doStart 方法子類會覆蓋:

在子類:SimpleMessageListenerContainer中:

@Override
	protected void doStart() throws Exception {
		……
		super.doStart();
		synchronized (this.consumersMonitor) {
            
			int newConsumers = initializeConsumers();
			
			Set<AsyncMessageProcessingConsumer> processors = new HashSet<AsyncMessageProcessingConsumer>();
			for (BlockingQueueConsumer consumer : this.consumers) {
                        //AsyncMessageProcessingConsumer是SimpleMessageListenerContainer的內部類
				AsyncMessageProcessingConsumer processor = new AsyncMessageProcessingConsumer(consumer);
				processors.add(processor);
                        //放入線程池
				getTaskExecutor().execute(processor);
				
			}
		
		}
	}

RabbitListenerAnnotationBeanPostProcessor調用SimpleMessageListenerContainer是AsyncMessageProcessingConsumer放入線程池中的。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章