netty笔记-Pipeline的事件触发
2018-07-12 本文已影响28人
兴浩
1. DefaultChannelPipeline的 fireChannelRead事件
DefaultChannelPipeline中事件的触发是通过fire开头的方法来触发,其内部调用了AbstractChannelHandlerContext的相关的invoke静态方法
@Override
public final ChannelPipeline fireUserEventTriggered(Object event) {
AbstractChannelHandlerContext.invokeUserEventTriggered(head, event);
return this;
}
@Override
public final ChannelPipeline fireChannelRead(Object msg) {
AbstractChannelHandlerContext.invokeChannelRead(head, msg);
return this;
}
@Override
public final ChannelPipeline fireChannelReadComplete() {
AbstractChannelHandlerContext.invokeChannelReadComplete(head);
return this;
}
2. invokeChannelRead静态方法
invokeChannelRead静态方法实际上是调用了AbstractChannelHandlerContext的invokeChannelRead实例方法
static void invokeChannelRead(final AbstractChannelHandlerContext next, Object msg) {
final Object m = next.pipeline.touch(ObjectUtil.checkNotNull(msg, "msg"), next);
EventExecutor executor = next.executor();
if (executor.inEventLoop()) {
next.invokeChannelRead(m);
} else {
executor.execute(new Runnable() {
@Override
public void run() {
next.invokeChannelRead(m);
}
});
}
}
3. invokeChannelRead实例方法
调用了handler()的channelRead方法
private void invokeChannelRead(Object msg) {
if (invokeHandler()) {
try {
((ChannelInboundHandler) handler()).channelRead(this, msg);
} catch (Throwable t) {
notifyHandlerException(t);
}
} else {
fireChannelRead(msg);
}
}
3.1 HeadContext
HeadContext实现了Handler接口,所以handler方法就返回其自己,最终调用的是HeadContext的channelRead方法
final class HeadContext extends AbstractChannelHandlerContext
implements ChannelOutboundHandler, ChannelInboundHandler {
@Override
public ChannelHandler handler() {
return this;
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ctx.fireChannelRead(msg);
}
}
4. AbstractChannelHandlerContext的fireChannelRead事件
@Override
public ChannelHandlerContext fireChannelRead(final Object msg) {
invokeChannelRead(findContextInbound(), msg);
return this;
}
这个环节应该看起来跟DefaultChannelPipeline的 fireChannelRead事件是很相似的,不同点在于这里调用的对象是findContextInbound()
4.1 findContextInbound
private AbstractChannelHandlerContext findContextInbound() {
AbstractChannelHandlerContext ctx = this;
do {
ctx = ctx.next;
} while (!ctx.inbound);
return ctx;
}
由于AbstractChannelHandlerContext是一个链表结果,其通过next寻找下个对象,所以next找到的对象应该是 1243这个引用对象
![](https://img.haomeiwen.com/i1297060/b3b4bbf3d05b9602.png)
5. 触发ChannelInboundHandler事件
public class EchoServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// 将消息记录到控制台
ByteBuf in = (ByteBuf) msg;
System.out.println( "Server received: " + in.toString(CharsetUtil.UTF_8));
// 将接收到的消息写给发送者,而不冲刷出站消息
ctx.write(in);
}
}
完整的堆栈流程信息
![](https://img.haomeiwen.com/i1297060/0044688ee5e38fe0.png)
6.ChannelInvoker的实现
![](https://img.haomeiwen.com/i1297060/a727e873c0d0a7f7.png)
实现ChannelInboundInvoker和ChannelOutboundInvoker的类有2种
- ChannelHandlerContext
- ChannelPipeline
7.ChannelPipeline和ChannelHandlerContext的关系
- DefaultChannelPipeline内部维护着ChannelHandlerContext链表关系,并且可以获取到Channel的信息
- ChannelHandlerContext对Channel和Handler起到了承上启下的作用,在初始时同同时可以获取Pipeline和Handler的信息,由于可以获取到Pipeline的信息,那么同时就可以获取到Channel的信息,从此可知ChannelHandlerContext可获取的信息是非常丰富的,也符合其ChannelHandlerContext类的定义
7.1DefaultChannelHandlerContext的初始化
private AbstractChannelHandlerContext newContext(EventExecutorGroup group,
String name, ChannelHandler handler) {
return new DefaultChannelHandlerContext(this, childExecutor(group), name, handler);
}
DefaultChannelHandlerContext(
DefaultChannelPipeline pipeline,
EventExecutor executor, String name, ChannelHandler handler) {
super(pipeline, executor, name, isInbound(handler), isOutbound(handler));
if (handler == null) {
throw new NullPointerException("handler");
}
this.handler = handler;
}
AbstractChannelHandlerContext(DefaultChannelPipeline pipeline,
EventExecutor executor, String name,
boolean inbound, boolean outbound) {
this.name = ObjectUtil.checkNotNull(name, "name");
this.pipeline = pipeline;
this.executor = executor;
this.inbound = inbound;
this.outbound = outbound;
ordered = executor == null || executor instanceof OrderedEventExecutor;
}