Netty4
Netty是一个和MINA相似的Java NIO框架,目前的最新版本是4.0.13,这两个框架的主要做者好像都是同一个韩国人。html
Channel
Channel是Netty最核心的接口,一个Channel就是一个联络Socket的通道,经过Channel,你能够对Socket进行各类操做。java
ChannelHandler
用Netty编写网络程序的时候,你不多直接操纵Channel,而是经过ChannelHandler来间接操纵Channel。apache
ChannelPipeline
ChannelPipeline实际上应该叫作ChannelHandlerPipeline,能够把ChannelPipeline当作是一个ChandlerHandler的链表,当须要对Channel进行某种处理的时候,Pipeline负责依次调用每个Handler进行处理。每一个Channel都有一个属于本身的Pipeline,调用Channel#pipeline()方法能够得到Channel的Pipeline,调用Pipeline#channel()方法能够得到Pipeline的Channel。api

ChannelPipeline的方法有不少,其中一部分是用来管理ChannelHandler的,以下面这些:promise
- ChannelPipeline addFirst(String name, ChannelHandler handler);
- ChannelPipeline addLast(String name, ChannelHandler handler);
- ChannelPipeline addBefore(String baseName, String name, ChannelHandler handler);
- ChannelPipeline addAfter(String baseName, String name, ChannelHandler handler);
- ChannelPipeline remove(ChannelHandler handler);
- ChannelHandler remove(String name);
- ChannelHandler removeFirst();
- ChannelHandler removeLast();
- ChannelPipeline replace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler);
- ChannelHandler replace(String oldName, String newName, ChannelHandler newHandler);
- ChannelHandler first();
- ChannelHandler last();
- ChannelHandler get(String name);
根据上面的方法,可以大概想象的到Pipeline按照什么样的方式组织Handler。网络
ChannelHandlerContext
ChannelPipeline并非直接管理ChannelHandler,而是经过ChannelHandlerContext来间接管理,这一点经过ChannelPipeline的默认实现DefaultChannelPipeline能够看出来。框架

调用ChannelHandlerContext#channel()方法能够获得和Context绑定的Channel,调用ChannelHandlerContext#handler()方法能够获得和Context绑定的Handler。ide
ChannelPipeline和ChannelHandlerContext默认实现函数
DefaultChannelHandlerContext和DefaultChannelPipeline是ChannelHandlerContext和ChannelPipeline的默认实现,下面是它们的部分代码:this
- final class DefaultChannelHandlerContext extends DefaultAttributeMap implements ChannelHandlerContext {
-
- volatile DefaultChannelHandlerContext next;
- volatile DefaultChannelHandlerContext prev;
-
- private final boolean inbound;
- private final boolean outbound;
- private final AbstractChannel channel;
- private final DefaultChannelPipeline pipeline;
- private final String name;
- private final ChannelHandler handler;
- private boolean removed;
-
- // ...
- }
- final class DefaultChannelPipeline implements ChannelPipeline {
- // ...
-
- final DefaultChannelHandlerContext head;
- final DefaultChannelHandlerContext tail;
-
- // ...
- }
从上面的代码能够看出,在DefaultPipeline内部,DefaultChannelHandlerContext组成了一个双向链表:

再来看看DefaultChannelPipeline的构造函数:
- public DefaultChannelPipeline(AbstractChannel channel) {
- if (channel == null) {
- throw new NullPointerException("channel");
- }
- this.channel = channel;
-
- TailHandler tailHandler = new TailHandler();
- tail = new DefaultChannelHandlerContext(this, null, generateName(tailHandler), tailHandler);
-
- HeadHandler headHandler = new HeadHandler(channel.unsafe());
- head = new DefaultChannelHandlerContext(this, null, generateName(headHandler), headHandler);
-
- head.next = tail;
- tail.prev = head;
- }
能够看到,DefaultChinnelPipeline内部使用了两个特殊的Handler来表示Handler链的头和尾:

ChannelHandler的种类
从上面DefaultChannelHandlerContext代码能够知道,Handler实际上分为两种,Inbound和Outbound,这一点也能够从ChannelHandler接口的子接口获得证实:
- public interface ChannelInboundHandler extends ChannelHandler {
- // ...
- }
-
- public interface ChannelOutboundHandler extends ChannelHandler {
- // ...
- }
事件的传播
为了搞清楚事件如何在Pipeline里传播,让咱们从Channel的抽象子类AbstractChannel开始,下面是AbstractChannel#write()方法的实现:
- public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {
- // ...
- @Override
- public Channel write(Object msg) {
- return pipeline.write(msg);
- }
- // ...
- }
AbstractChannel直接调用了Pipeline的write()方法:

再看DefaultChannelPipeline的write()方法实现:
- final class DefaultChannelPipeline implements ChannelPipeline {
- // ...
- @Override
- public ChannelFuture write(Object msg) {
- return tail.write(msg);
- }
- // ...
- }
由于write是个outbound事件,因此DefaultChannelPipeline直接找到tail部分的context,调用其write()方法:

接着看DefaultChannelHandlerContext的write()方法:
- final class DefaultChannelHandlerContext extends DefaultAttributeMap implements ChannelHandlerContext {
- // ...
- @Override
- public ChannelFuture write(Object msg) {
- return write(msg, newPromise());
- }
-
- @Override
- public ChannelFuture write(final Object msg, final ChannelPromise promise) {
- if (msg == null) {
- throw new NullPointerException("msg");
- }
-
- validatePromise(promise, true);
-
- write(msg, false, promise);
-
- return promise;
- }
-
- private void write(Object msg, boolean flush, ChannelPromise promise) {
- DefaultChannelHandlerContext next = findContextOutbound();
- next.invokeWrite(msg, promise);
- if (flush) {
- next.invokeFlush();
- }
- }
-
- private DefaultChannelHandlerContext findContextOutbound() {
- DefaultChannelHandlerContext ctx = this;
- do {
- ctx = ctx.prev;
- } while (!ctx.outbound);
- return ctx;
- }
-
- private void invokeWrite(Object msg, ChannelPromise promise) {
- try {
- ((ChannelOutboundHandler) handler).write(this, msg, promise);
- } catch (Throwable t) {
- notifyOutboundHandlerException(t, promise);
- }
- }
-
- // ...
- }
context的write()方法沿着context链往前找,直至找到一个outbound类型的context为止,而后调用其invokeWrite()方法:

invokeWrite()接着调用handler的write()方法:

最后看看ChannelOutboundHandlerAdapter的write()方法实现:
- public class ChannelOutboundHandlerAdapter extends ChannelHandlerAdapter implements ChannelOutboundHandler {
- // ...
- @Override
- public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
- ctx.write(msg, promise);
- }
- // ...
- }
默认的实现调用了context的write()方法而不作任何处理,这样write事件就沿着outbound链继续传播:

可见,Pipeline的事件传播,是靠Pipeline,Context和Handler共同协做完成的。
参考资料
netty.io
Netty in Action
Intercepting Filter