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 + ")";
}
}