目錄
2、RabbitListenerContainerFactory
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放入線程池中的。