Netty4
Netty是一個(gè)和MINA類似的Java NIO框架,目前的最新版本是4.0.13,這兩個(gè)框架的主要作者好像都是同一個(gè)韓國人。
Channel
Channel是Netty最核心的接口,一個(gè)Channel就是一個(gè)聯(lián)絡(luò)Socket的通道,通過Channel,你可以對(duì)Socket進(jìn)行各種操作。
ChannelHandler
用Netty編寫網(wǎng)絡(luò)程序的時(shí)候,你很少直接操縱Channel,而是通過ChannelHandler來間接操縱Channel。
ChannelPipeline
ChannelPipeline實(shí)際上應(yīng)該叫做ChannelHandlerPipeline,可以把ChannelPipeline看成是一個(gè)ChandlerHandler的鏈表,當(dāng)需要對(duì)Channel進(jìn)行某種處理的時(shí)候,Pipeline負(fù)責(zé)依次調(diào)用每一個(gè)Handler進(jìn)行處理。每個(gè)Channel都有一個(gè)屬于自己的Pipeline,調(diào)用Channel#pipeline()方法可以獲得Channel的Pipeline,調(diào)用Pipeline#channel()方法可以獲得Pipeline的Channel。

ChannelPipeline的方法有很多,其中一部分是用來管理ChannelHandler的,如下面這些:
- 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);
根據(jù)上面的方法,能夠大概想象的到Pipeline按照什么樣的方式組織Handler。
ChannelHandlerContext
ChannelPipeline并不是直接管理ChannelHandler,而是通過ChannelHandlerContext來間接管理,這一點(diǎn)通過ChannelPipeline的默認(rèn)實(shí)現(xiàn)DefaultChannelPipeline可以看出來。

調(diào)用ChannelHandlerContext#channel()方法可以得到和Context綁定的Channel,調(diào)用ChannelHandlerContext#handler()方法可以得到和Context綁定的Handler。
ChannelPipeline和ChannelHandlerContext默認(rèn)實(shí)現(xiàn)
DefaultChannelHandlerContext和DefaultChannelPipeline是ChannelHandlerContext和ChannelPipeline的默認(rèn)實(shí)現(xiàn),下面是它們的部分代碼:
- 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內(nèi)部,DefaultChannelHandlerContext組成了一個(gè)雙向鏈表:

再來看看DefaultChannelPipeline的構(gòu)造函數(shù):
- 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內(nèi)部使用了兩個(gè)特殊的Handler來表示Handler鏈的頭和尾:

ChannelHandler的種類
從上面DefaultChannelHandlerContext代碼可以知道,Handler實(shí)際上分為兩種,Inbound和Outbound,這一點(diǎn)也可以從ChannelHandler接口的子接口得到證明:
- public interface ChannelInboundHandler extends ChannelHandler {
- // ...
- }
-
- public interface ChannelOutboundHandler extends ChannelHandler {
- // ...
- }
事件的傳播
為了搞清楚事件如何在Pipeline里傳播,讓我們從Channel的抽象子類AbstractChannel開始,下面是AbstractChannel#write()方法的實(shí)現(xiàn):
- public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {
- // ...
- @Override
- public Channel write(Object msg) {
- return pipeline.write(msg);
- }
- // ...
- }
AbstractChannel直接調(diào)用了Pipeline的write()方法:

再看DefaultChannelPipeline的write()方法實(shí)現(xiàn):
- final class DefaultChannelPipeline implements ChannelPipeline {
- // ...
- @Override
- public ChannelFuture write(Object msg) {
- return tail.write(msg);
- }
- // ...
- }
因?yàn)閣rite是個(gè)outbound事件,所以DefaultChannelPipeline直接找到tail部分的context,調(diào)用其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鏈往前找,直至找到一個(gè)outbound類型的context為止,然后調(diào)用其invokeWrite()方法:

invokeWrite()接著調(diào)用handler的write()方法:

最后看看ChannelOutboundHandlerAdapter的write()方法實(shí)現(xiàn):
- public class ChannelOutboundHandlerAdapter extends ChannelHandlerAdapter implements ChannelOutboundHandler {
- // ...
- @Override
- public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
- ctx.write(msg, promise);
- }
- // ...
- }
默認(rèn)的實(shí)現(xiàn)調(diào)用了context的write()方法而不做任何處理,這樣write事件就沿著outbound鏈繼續(xù)傳播:

可見,Pipeline的事件傳播,是靠Pipeline,Context和Handler共同協(xié)作完成的。
參考資料
Netty in Action
Intercepting Filter
|