ChannelPipeline、ChannelHandlerContext和ChannelHandler三者之间关系的模型:
接下来稍微了解一下ChannelHandler的类模型吧
从中可以看见,Channel有inbound和outbound之分
再看一下ChannelInboundHandler、ChannelOutboundHandler的方法:
可以看到其实有些ChannelHandler的有些操作属于outbound,有些属于intbound操作,分别被封装在ChannelOutBoundHandler和ChannelInboundHandler中
再看一下ChannelHandlerContext的实现类DefaultChannelHandlerContext的属性
再看一下ChannelPipeline实现类DefaultChannelPipeline
从上面代码可以看出来,其实生成的DefaultChannelPipe中的ChannelHandlerContext双向链表就是一个
而HeadHandler其实就是一个ChannelOutboundHandler类,而TailHandler其实就是一个ChannelInboundHandler类
我们看一下DefaultChannelHandlerContext一些操作方法
从中可以看到属于inboudHandler的方法前面都带有一个fire,再看一下outbound、和inboud两种方法的操作上有什么大的区别呢?
先看一下inbound操作的register(就以register为代表吧)操作
//DefaultChannelPipeline
@Override
public ChannelPipeline fireChannelRegistered() {
head.fireChannelRegistered(); //head是一个HeadHandler对应的DefaultChannelHandlerContext
return this;
}
再看DefaultChannelHandlerContext中的实现
//DefaultChannelHandlerContext
@Override
public ChannelHandlerContext fireChannelRegistered() {
final DefaultChannelHandlerContext next = findContextInbound(); // 找到下一个ChannelInboudHandler
EventExecutor executor = next.executor();
if (executor.inEventLoop()) {
next.invokeChannelRegistered();
} else {
executor.execute(new Runnable() {
@Override
public void run() {
next.invokeChannelRegistered();
}
});
}
return this;
}
private void invokeChannelRegistered() {
try {
((ChannelInboundHandler) handler).channelRegistered(this);
} catch (Throwable t) {
notifyHandlerException(t);
}
}
//DefaultChannelHandlerContext
private DefaultChannelHandlerContext findContextInbound() {
DefaultChannelHandlerContext ctx = this;
do {
ctx = ctx.next;
} while (!ctx.inbound);
return ctx;
}
incokeChannelRegistered()中将register交给了ChannelInboundHandler中的channelRegistered()来实现,再看ChannelInboundHandlerAdapter中的实现
//ChannelInboundHandlerAdapter
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
ctx.fireChannelRegistered();
}
可见这就是一个循环反复的执行过程,最后以tail的空实现结束。当然你可以再加入自定义的ChannelInboundHandler,对channelRegistered(this)进行重写
再看outbound的channelhandler,我们以read()方法为代表吧
首先我们看一下DefaultChannelPipe中的read()方法吧
//DefaultChannelPipeline
@Override
public ChannelPipeline read() {
tail.read(); //tail是TailHandler对应的DefaultChannelHandlerContext
return this;
}
//DefaultChannelHandlerContext
@Override
public ChannelHandlerContext read() {
final DefaultChannelHandlerContext next = findContextOutbound(); //找到下一个outbound对应的DefaultChannelHandlerContext
EventExecutor executor = next.executor();
if (executor.inEventLoop()) {
next.invokeRead();
} else {
Runnable task = next.invokeReadTask;
if (task == null) {
next.invokeReadTask = task = new Runnable() {
@Override
public void run() {
next.invokeRead();
}
};
}
executor.execute(task);
}
return this;
}
private void invokeRead() {
try {
((ChannelOutboundHandler) handler).read(this);
} catch (Throwable t) {
notifyHandlerException(t);
}
}
//DefaultChannelHandlerContext
private DefaultChannelHandlerContext findContextOutbound() {
DefaultChannelHandlerContext ctx = this;
do {
ctx = ctx.prev;
} while (!ctx.outbound);
return ctx;
}
所以ChannelHandler的read()方法也是自己有自己定义,不然他就可以一直运行到HeadHandler中read()方法
所以ChannelHandler的运行过程就是这样的:
当然其中图里面应该是ChannelContext,在这里用handler代理
好了,至此,整个过程也就结束了,可见其实inbound和outboud在ChannelPipe中的实现方式也是差不多的
到这里,你应该理解了他的整个运行过程了,找个例子亲自调试一下,你会理解更透彻的