Artemis的JMS客户端中的CompletionHandler是如何在artemis core api中传递及调用的

ActiveMQChannelHandler

NettyConnector在公开的start方法中,为Channel的pipeline设置了ActiveMQChannelHandler(继承于io.netty.channel.ChannelDuplexHandler)回调句柄。
ActiveMQChannelHandler其构造函数定义如下:

ActiveMQChannelHandler(final ChannelGroup group,
                       final BufferHandler handler,
                       final BaseConnectionLifeCycleListener listener)

可见它接收了一个BufferHandler对象。在其channelRead这个callback方法中,调用了这个BufferHandler对象bufferReceived方法。

如此看来,如果想要Netty异步通信完毕后,处理一些回调,则只需实现BufferHandler,并在适当的位置设置到Netty的Channel的pipeline里。


BufferHandler

ClientSessionFactoryImpl在其保护方法createConnector里,创建了NettyConnector对象,并传入了DelegatingBufferHandler。
DelegatingBufferHandler实现了BufferHandler,可用来处理Netty回调。


DelegatingBufferHandler

DelegatingBufferHandler定义如下,它是定义在ClientSessionFactoryImpl类里的:

private class DelegatingBufferHandler implements BufferHandler {

      @Override
      public void bufferReceived(final Object connectionID, final ActiveMQBuffer buffer) {
         RemotingConnection theConn = connection;

         if (theConn != null && connectionID.equals(theConn.getID())) {
            theConn.bufferReceived(connectionID, buffer);
         } else {
            logger.debug("TheConn == null on ClientSessionFactoryImpl::DelegatingBufferHandler, ignoring packet");
         }
      }
   }

也就是说,在Netty执行回调时,会调用ClientSessionFactory中的成员对象connection(类型:RemotingConnection)的bufferReceived方法来处理数据。

实际上RemotingConnection也是一种BufferHandler


RemotingConnection

RemotingConnection(Impl)实现了bufferReceived(connectionID, buffer)方法,该方法会根据传入的buffer来decode出一个package。
bufferReceived
=> doBufferReceived (以下ChannelImpl对应的实例,是根据decode出来的package对应的channelID,到RemotingConnectionImpl包含的channel集合里取得的)
=> ChannelImpl::doBufferReceived
=> ChannelImpl::handlePacket
=> ChannelImpl::clearUpTo
=> commandConfirmationHandler.commandConfirmed(packet)

举例:Artemis中实现的JMS规范下的Producer在异步投递消息后的回调函数是如何被调用的

以ArtemisMQMessageProducer为例:

  • 他的send方法中,最后是调用core api的ClientProducer的send方法的,传入一个core api的handler —— CompletionListenerWrapper(继承于SendAcknowledgementHandler类型),它包装了JMS的CompletionListener。

  • 再转到ClientProducer的send方法, 它又调用了doSend方法,

  • 然后它又调用了sendRegularMessage方法,它又调用了sessionContext.sendFullMessage方法。

  • 在sessionContext.sendFullMessage方法里,可以看到,handler被包装到packet里了,并且传给了sessionChannel.sendBatched(packet)方法去异步发送了。

  • 在服务器返回的packet里,也会带有这个handler,然后BufferHandler的实现者RemotingConnection(Impl)的bufferReceived方法会被回调,它会解析服务器回传的packet里的handler进行执行。

packet是SessionSendMessage类型的消息的别名
sessionContext.sendFullMessage方法里负责将SendAcknowledgementHandler包装到SessionSendMessage类型的packet里,然后才发送至服务器
服务器返回的packet,也会首先被转换成SessionSendMessage类型,然后获取里面包含的SendAcknowledgementHandler类型的回调handler执行回调。

CompletionListenerWrapper类定义:

private static final class CompletionListenerWrapper implements SendAcknowledgementHandler {

      private final CompletionListener completionListener;
      private final Message jmsMessage;
      private final ActiveMQMessageProducer producer;

      /**
       * @param jmsMessage
       * @param producer
       */
      private CompletionListenerWrapper(CompletionListener listener,
                                        Message jmsMessage,
                                        ActiveMQMessageProducer producer) {
         this.completionListener = listener;
         this.jmsMessage = jmsMessage;
         this.producer = producer;
      }

      @Override
      public void sendAcknowledged(org.apache.activemq.artemis.api.core.Message clientMessage) {
         if (jmsMessage instanceof StreamMessage) {
            try {
               ((StreamMessage) jmsMessage).reset();
            } catch (JMSException e) {
               // HORNETQ-1209 XXX ignore?
            }
         }
         if (jmsMessage instanceof BytesMessage) {
            try {
               ((BytesMessage) jmsMessage).reset();
            } catch (JMSException e) {
               // HORNETQ-1209 XXX ignore?
            }
         }

         try {
            producer.connection.getThreadAwareContext().setCurrentThread(true);
            completionListener.onCompletion(jmsMessage);
         } finally {
            producer.connection.getThreadAwareContext().clearCurrentThread(true);
         }
      }

      @Override
      public String toString() {
         return CompletionListenerWrapper.class.getSimpleName() + "( completionListener=" + completionListener + ")";
      }
   }

你可能感兴趣的:(java,activemq,queue)