备注:本文的分析基于netty 4.0.9final版本

1、ChannelPipeline结构图

netty4.0.x源码分析—ChannelPipeline_java

2、关键类和接口分析

上一篇关于Channel的文章,在AbstractChannel的介绍中,以及提到了pipeline,这是操作处理的入口,是一个比较重要的概念,这里有必要对pipeline分析一下。

1)ChannelInboundInvoker




1. /**
2.  * Interface which is shared by others which need to fire inbound events
3.  */  
4. interface ChannelInboundInvoker {  
5.   
6. /**
7.      * A {@link Channel} was registered to its {@link EventLoop}.
8.      *
9.      * This will result in having the  {@link ChannelInboundHandler#channelRegistered(ChannelHandlerContext)} method
10.      * called of the next  {@link ChannelInboundHandler} contained in the  {@link ChannelPipeline} of the
11.      * {@link Channel}.
12.      */  
13.     ChannelInboundInvoker fireChannelRegistered();  
14.   
15. /**
16.      * A {@link Channel} was unregistered from its {@link EventLoop}.
17.      *
18.      * This will result in having the  {@link ChannelInboundHandler#channelUnregistered(ChannelHandlerContext)} method
19.      * called of the next  {@link ChannelInboundHandler} contained in the  {@link ChannelPipeline} of the
20.      * {@link Channel}.
21.      */  
22. @Deprecated  
23.     ChannelInboundInvoker fireChannelUnregistered();  
24.   
25. /**
26.      * A {@link Channel} is active now, which means it is connected.
27.      *
28.      * This will result in having the  {@link ChannelInboundHandler#channelActive(ChannelHandlerContext)} method
29.      * called of the next  {@link ChannelInboundHandler} contained in the  {@link ChannelPipeline} of the
30.      * {@link Channel}.
31.      */  
32.     ChannelInboundInvoker fireChannelActive();  
33.   
34. /**
35.      * A {@link Channel} is inactive now, which means it is closed.
36.      *
37.      * This will result in having the  {@link ChannelInboundHandler#channelInactive(ChannelHandlerContext)} method
38.      * called of the next  {@link ChannelInboundHandler} contained in the  {@link ChannelPipeline} of the
39.      * {@link Channel}.
40.      */  
41.     ChannelInboundInvoker fireChannelInactive();  
42.   
43. /**
44.      * A {@link Channel} received an {@link Throwable} in one of its inbound operations.
45.      *
46.      * This will result in having the  {@link ChannelInboundHandler#exceptionCaught(ChannelHandlerContext, Throwable)}
47.      * method  called of the next  {@link ChannelInboundHandler} contained in the  {@link ChannelPipeline} of the
48.      * {@link Channel}.
49.      */  
50.     ChannelInboundInvoker fireExceptionCaught(Throwable cause);  
51.   
52. /**
53.      * A {@link Channel} received an user defined event.
54.      *
55.      * This will result in having the  {@link ChannelInboundHandler#userEventTriggered(ChannelHandlerContext, Object)}
56.      * method  called of the next  {@link ChannelInboundHandler} contained in the  {@link ChannelPipeline} of the
57.      * {@link Channel}.
58.      */  
59.     ChannelInboundInvoker fireUserEventTriggered(Object event);  
60.   
61. /**
62.      * A {@link Channel} received a message.
63.      *
64.      * This will result in having the {@link ChannelInboundHandler#channelRead(ChannelHandlerContext, Object)}
65.      * method  called of the next {@link ChannelInboundHandler} contained in the  {@link ChannelPipeline} of the
66.      * {@link Channel}.
67.      */  
68.     ChannelInboundInvoker fireChannelRead(Object msg);  
69.   
70.     ChannelInboundInvoker fireChannelReadComplete();  
71.   
72. /**
73.      * Triggers an {@link ChannelInboundHandler#channelWritabilityChanged(ChannelHandlerContext)}
74.      * event to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}.
75.      */  
76.     ChannelInboundInvoker fireChannelWritabilityChanged();  
77. }


这接口定义比较简单,即有事件数据从底层到应用时,用它来做相应的处理。



2)ChannelOutboundInvoker


1. /**
2.  * Interface which is shared by others which need to execute outbound logic.
3.  */  
4. interface ChannelOutboundInvoker {  
5.   
6. /**
7.      * Request to bind to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation
8.      * completes, either because the operation was successful or because of an error.
9.      * <p>
10.      * This will result in having the
11.      * {@link ChannelOutboundHandler#bind(ChannelHandlerContext, SocketAddress, ChannelPromise)} method
12.      * called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the
13.      * {@link Channel}.
14.      */  
15.     ChannelFuture bind(SocketAddress localAddress);  
16.   
17. /**
18.      * Request to connect to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation
19.      * completes, either because the operation was successful or because of an error.
20.      * <p>
21.      * If the connection fails because of a connection timeout, the {@link ChannelFuture} will get failed with
22.      * a {@link ConnectTimeoutException}. If it fails because of connection refused a {@link ConnectException}
23.      * will be used.
24.      * <p>
25.      * This will result in having the
26.      * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)}
27.      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the
28.      * {@link Channel}.
29.      */  
30.     ChannelFuture connect(SocketAddress remoteAddress);  
31.   
32. /**
33.      * Request to connect to the given {@link SocketAddress} while bind to the localAddress and notify the
34.      * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of
35.      * an error.
36.      * <p>
37.      * This will result in having the
38.      * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)}
39.      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the
40.      * {@link Channel}.
41.      */  
42.     ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress);  
43.   
44. /**
45.      * Request to disconnect from the remote peer and notify the {@link ChannelFuture} once the operation completes,
46.      * either because the operation was successful or because of an error.
47.      * <p>
48.      * This will result in having the
49.      * {@link ChannelOutboundHandler#disconnect(ChannelHandlerContext, ChannelPromise)}
50.      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the
51.      * {@link Channel}.
52.      */  
53.     ChannelFuture disconnect();  
54.   
55. /**
56.      * Request to close this ChannelOutboundInvoker and notify the {@link ChannelFuture} once the operation completes,
57.      * either because the operation was successful or because of
58.      * an error.
59.      *
60.      * After it is closed it is not possible to reuse it again.
61.      * <p>
62.      * This will result in having the
63.      * {@link ChannelOutboundHandler#close(ChannelHandlerContext, ChannelPromise)}
64.      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the
65.      * {@link Channel}.
66.      */  
67.     ChannelFuture close();  
68.   
69. /**
70.      * Request to deregister this ChannelOutboundInvoker from the previous assigned {@link EventExecutor} and notify the
71.      * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of
72.      * an error.
73.      * <p>
74.      * This will result in having the
75.      * {@link ChannelOutboundHandler#deregister(ChannelHandlerContext, ChannelPromise)}
76.      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the
77.      * {@link Channel}.
78.      *
79.      */  
80. @Deprecated  
81.     ChannelFuture deregister();  
82.   
83. /**
84.      * Request to bind to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation
85.      * completes, either because the operation was successful or because of an error.
86.      *
87.      * The given {@link ChannelPromise} will be notified.
88.      * <p>
89.      * This will result in having the
90.      * {@link ChannelOutboundHandler#bind(ChannelHandlerContext, SocketAddress, ChannelPromise)} method
91.      * called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the
92.      * {@link Channel}.
93.      */  
94.     ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise);  
95.   
96. /**
97.      * Request to connect to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation
98.      * completes, either because the operation was successful or because of an error.
99.      *
100.      * The given {@link ChannelFuture} will be notified.
101.      *
102.      * <p>
103.      * If the connection fails because of a connection timeout, the {@link ChannelFuture} will get failed with
104.      * a {@link ConnectTimeoutException}. If it fails because of connection refused a {@link ConnectException}
105.      * will be used.
106.      * <p>
107.      * This will result in having the
108.      * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)}
109.      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the
110.      * {@link Channel}.
111.      */  
112.     ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise);  
113.   
114. /**
115.      * Request to connect to the given {@link SocketAddress} while bind to the localAddress and notify the
116.      * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of
117.      * an error.
118.      *
119.      * The given {@link ChannelPromise} will be notified and also returned.
120.      * <p>
121.      * This will result in having the
122.      * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)}
123.      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the
124.      * {@link Channel}.
125.      */  
126.     ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise);  
127.   
128. /**
129.      * Request to disconnect from the remote peer and notify the {@link ChannelFuture} once the operation completes,
130.      * either because the operation was successful or because of an error.
131.      *
132.      * The given {@link ChannelPromise} will be notified.
133.      * <p>
134.      * This will result in having the
135.      * {@link ChannelOutboundHandler#disconnect(ChannelHandlerContext, ChannelPromise)}
136.      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the
137.      * {@link Channel}.
138.      */  
139.     ChannelFuture disconnect(ChannelPromise promise);  
140.   
141. /**
142.      * Request to close this ChannelOutboundInvoker and notify the {@link ChannelFuture} once the operation completes,
143.      * either because the operation was successful or because of
144.      * an error.
145.      *
146.      * After it is closed it is not possible to reuse it again.
147.      * The given {@link ChannelPromise} will be notified.
148.      * <p>
149.      * This will result in having the
150.      * {@link ChannelOutboundHandler#close(ChannelHandlerContext, ChannelPromise)}
151.      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the
152.      * {@link Channel}.
153.      */  
154.     ChannelFuture close(ChannelPromise promise);  
155.   
156. /**
157.      * Request to deregister this ChannelOutboundInvoker from the previous assigned {@link EventExecutor} and notify the
158.      * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of
159.      * an error.
160.      *
161.      * The given {@link ChannelPromise} will be notified.
162.      * <p>
163.      * This will result in having the
164.      * {@link ChannelOutboundHandler#deregister(ChannelHandlerContext, ChannelPromise)}
165.      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the
166.      * {@link Channel}.
167.      */  
168. @Deprecated  
169.     ChannelFuture deregister(ChannelPromise promise);  
170.   
171. /**
172.      * Request to Read data from the {@link Channel} into the first inbound buffer, triggers an
173.      * {@link ChannelInboundHandler#channelRead(ChannelHandlerContext, Object)} event if data was
174.      * read, and triggers a
175.      * {@link ChannelInboundHandler#channelReadComplete(ChannelHandlerContext) channelReadComplete} event so the
176.      * handler can decide to continue reading.  If there's a pending read operation already, this method does nothing.
177.      * <p>
178.      * This will result in having the
179.      * {@link ChannelOutboundHandler#read(ChannelHandlerContext)}
180.      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the
181.      * {@link Channel}.
182.      */  
183.     ChannelOutboundInvoker read();  
184.   
185. /**
186.      * Request to write a message via this ChannelOutboundInvoker through the {@link ChannelPipeline}.
187.      * This method will not request to actual flush, so be sure to call {@link #flush()}
188.      * once you want to request to flush all pending data to the actual transport.
189.      */  
190.     ChannelFuture write(Object msg);  
191.   
192. /**
193.      * Request to write a message via this ChannelOutboundInvoker through the {@link ChannelPipeline}.
194.      * This method will not request to actual flush, so be sure to call {@link #flush()}
195.      * once you want to request to flush all pending data to the actual transport.
196.      */  
197.     ChannelFuture write(Object msg, ChannelPromise promise);  
198.   
199. /**
200.      * Request to flush all pending messages via this ChannelOutboundInvoker.
201.      */  
202.     ChannelOutboundInvoker flush();  
203.   
204. /**
205.      * Shortcut for call {@link #write(Object, ChannelPromise)} and {@link #flush()}.
206.      */  
207.     ChannelFuture writeAndFlush(Object msg, ChannelPromise promise);  
208.   
209. /**
210.      * Shortcut for call {@link #write(Object)} and {@link #flush()}.
211.      */  
212.     ChannelFuture writeAndFlush(Object msg);  
213. }

这个接口定义用于处理从应用到底层的事件数据。



3)ChannelPipeline

ChannelPipeline继承ChannelInboundInvoker和ChannelOutboundInvoker,它既是一个inboundinvoke,又是一个outboundinvoke,同时它也是ChannelHandler的管理者,提供了很多方法对handler进行操作。


4)DefaultChannelPipeline

在分析DefaultChannelPipeline之前,不得不先分析DefaultChannelHandlerContext(实现ChannelHandlerContext),因为ChannelPipeline的所有handler执行都是间接由ChannelhandlerContext执行的,在后面DefaultChannelPipeline的定义中,我们可以看到这点。

ChannelHandlerContext接口定义了很多方法,关键代码如下:



1. /**
2.  * Return the {@link Channel} which is bound to the {@link ChannelHandlerContext}.
3.  */  
4. Channel channel();  
5.   
6. /**
7.  * The {@link EventExecutor} that is used to dispatch the events. This can also be used to directly
8.  * submit tasks that get executed in the event loop. For more information please refer to the
9.  * {@link EventExecutor} javadoc.
10.  */  
11. EventExecutor executor();


返回当前HandlerContext的Channel,以及返回当前EventExcutor。


DefaultChannelHandlerContext具体的final类,关键代码如下:


1. volatile DefaultChannelHandlerContext next;  
2. volatile DefaultChannelHandlerContext prev;  
3.   
4. private final boolean inbound;  
5. private final boolean outbound;  
6. private final AbstractChannel channel;  
7. private final DefaultChannelPipeline pipeline;  
8. private final String name;  
9. private final ChannelHandler handler;  
10. private boolean removed;  
11.   
12. // Will be set to null if no child executor should be used, otherwise it will be set to the  
13. // child executor.  
14. final EventExecutor executor;  
15. private ChannelFuture succeededFuture;


从上述代码中可以看出,DefaultChannelHandlerContext其实是一个上下文环境,它里面包括了当前Channel,当前的pipeline,以及当前的handler。另外它还提供了很多方法的实现,列如下面的函数。

    1. @Override  
    2. public ChannelHandlerContext fireChannelActive() {  
    3. final DefaultChannelHandlerContext next = findContextInbound();  
    4.     EventExecutor executor = next.executor();  
    5. if (executor.inEventLoop()) {  
    6.         next.invokeChannelActive();  
    7. else {  
    8. new Runnable() {  
    9. @Override  
    10. public void run() {  
    11.                 next.invokeChannelActive();  
    12.             }  
    13.         });  
    14.     }  
    15. return this;  
    16. }


    从这个函数中,可以看出Handler的执行是由executor以线程的方式执行的。



    分析完DefaultChannelHandlerContext,下面再来看DefaultChannelPipeline(实现Channelpipeline)。它是一个具体的handler管理者,handler的类型可以是inboundhandler,也可以是outboundhandler。关键代码如下:



    1. final AbstractChannel channel;  
    2.   
    3. final DefaultChannelHandlerContext head;  
    4. final DefaultChannelHandlerContext tail;  
    5.   
    6. private final Map<String, DefaultChannelHandlerContext> name2ctx =  
    7. new HashMap<String, DefaultChannelHandlerContext>(4);  
    8.   
    9. final Map<EventExecutorGroup, EventExecutor> childExecutors =  
    10. new IdentityHashMap<EventExecutorGroup, EventExecutor>();  
    11.   
    12. public DefaultChannelPipeline(AbstractChannel channel) {  
    13. if (channel == null) {  
    14. throw new NullPointerException("channel");  
    15.     }  
    16. this.channel = channel;  
    17.   
    18. new TailHandler();  
    19. new DefaultChannelHandlerContext(this, null, generateName(tailHandler), tailHandler);  
    20.   
    21. new HeadHandler(channel.unsafe());  
    22. new DefaultChannelHandlerContext(this, null, generateName(headHandler), headHandler);  
    23.   
    24.     head.next = tail;  
    25.     tail.prev = head;  
    26. }

    从上述代码中可以看出,每个Channel都有一个对应的pipeline,每个pipeline有两个ChannelHandlerContext,分别包含默认的TailHandler和HeadHandler,并且它们构成一个双向链表结构。TailHandler处理inbound类型的数据;HeadHandler处理outbound类型的数据。


    TailHandler是一个内部类,它实现ChannelInboundHandler接口,定义如下:


    1. // A special catch-all handler that handles both bytes and messages.  
    2. static final class TailHandler implements ChannelInboundHandler {  
    3.   
    4. @Override  
    5. public void channelRegistered(ChannelHandlerContext ctx) throws Exception { }  
    6.   
    7. @Override  
    8. public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { }  
    9.   
    10. @Override  
    11. public void channelActive(ChannelHandlerContext ctx) throws Exception { }  
    12.   
    13. @Override  
    14. public void channelInactive(ChannelHandlerContext ctx) throws Exception { }  
    15.   
    16. @Override  
    17. public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception { }  
    18.   
    19. @Override  
    20. public void handlerAdded(ChannelHandlerContext ctx) throws Exception { }  
    21.   
    22. @Override  
    23. public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { }  
    24.   
    25. @Override  
    26. public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { }  
    27.   
    28. @Override  
    29. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {  
    30.         logger.warn(  
    31. "An exceptionCaught() event was fired, and it reached at the tail of the pipeline. " +  
    32. "It usually means the last handler in the pipeline did not handle the exception.", cause);  
    33.     }  
    34.   
    35. @Override  
    36. public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {  
    37. try {  
    38.             logger.debug(  
    39. "Discarded inbound message {} that reached at the tail of the pipeline. " +  
    40. "Please check your pipeline configuration.", msg);  
    41. finally {  
    42.             ReferenceCountUtil.release(msg);  
    43.         }  
    44.     }  
    45.   
    46. @Override  
    47. public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { }  
    48. }


    TailHandler的实现函数都是空的,这说明对于底层上来应用的数据,用户必须定义Handler来处理,不能使用默认的Handler进行处理。


    HeadHandler也是一个内部类,它实现ChannelOutboundHandler接口,定义如下:



    1. static final class HeadHandler implements ChannelOutboundHandler {  
    2.   
    3. protected final Unsafe unsafe;  
    4.   
    5. protected HeadHandler(Unsafe unsafe) {  
    6. this.unsafe = unsafe;  
    7.     }  
    8.   
    9. @Override  
    10. public void handlerAdded(ChannelHandlerContext ctx) throws Exception {  
    11. // NOOP  
    12.     }  
    13.   
    14. @Override  
    15. public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {  
    16. // NOOP  
    17.     }  
    18.   
    19. @Override  
    20. public void bind(  
    21.             ChannelHandlerContext ctx, SocketAddress localAddress, ChannelPromise promise)  
    22. throws Exception {  
    23.         unsafe.bind(localAddress, promise);  
    24.     }  
    25.   
    26. @Override  
    27. public void connect(  
    28.             ChannelHandlerContext ctx,  
    29.             SocketAddress remoteAddress, SocketAddress localAddress,  
    30. throws Exception {  
    31.         unsafe.connect(remoteAddress, localAddress, promise);  
    32.     }  
    33.   
    34. @Override  
    35. public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {  
    36.         unsafe.disconnect(promise);  
    37.     }  
    38.   
    39. @Override  
    40. public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {  
    41.         unsafe.close(promise);  
    42.     }  
    43.   
    44. @Override  
    45. public void deregister(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {  
    46.         unsafe.deregister(promise);  
    47.     }  
    48.   
    49. @Override  
    50. public void read(ChannelHandlerContext ctx) {  
    51.         unsafe.beginRead();  
    52.     }  
    53.   
    54. @Override  
    55. public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {  
    56.         unsafe.write(msg, promise);  
    57.     }  
    58.   
    59. @Override  
    60. public void flush(ChannelHandlerContext ctx) throws Exception {  
    61.         unsafe.flush();  
    62.     }  
    63.   
    64. @Override  
    65. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {  
    66.         ctx.fireExceptionCaught(cause);  
    67.     }  
    68. }

    HeaderHandler的实现函数都是基于unsafe对象的函数实现的,所以对于OutBound类型的数据,即应用往底层的数据,可以使用默认的Handler进行处理。



    3、基于DefaultChannelPipeline的fireChannelActive函数分析handler的调用过程

    1)fireChannelActive定义


    1. @Override  
    2. public ChannelPipeline fireChannelActive() {  
    3.     head.fireChannelActive();  
    4.   
    5. if (channel.config().isAutoRead()) {  
    6.         channel.read();  
    7.     }  
    8.   
    9. return this;  
    10. }



    2) fireChannelActive实现分析


    1. @Override  
    2. public ChannelHandlerContext fireChannelActive() {  
    3. final DefaultChannelHandlerContext next = findContextInbound();  
    4.     EventExecutor executor = next.executor();  
    5. if (executor.inEventLoop()) {  
    6.         next.invokeChannelActive();  
    7. else {  
    8. new Runnable() {  
    9. @Override  
    10. public void run() {  
    11.                 next.invokeChannelActive();  
    12.             }  
    13.         });  
    14.     }  
    15. return this;  
    16. }<pre name="code" class="java">    private DefaultChannelHandlerContext findContextInbound() {  
    17. this;  
    18. do {  
    19.         ctx = ctx.next;  
    20. while (!ctx.inbound);  
    21. return ctx;  
    22. }


      1. private void invokeChannelActive() {  
      2. try {  
      3. this);  
      4. catch (Throwable t) {  
      5.         notifyHandlerException(t);  
      6.     }  
      7. }


      上面的代码逻辑还是比较简单的,就是从Channelhandlercontext的Head链表中获取上下文,然后调用相应的Handler执行函数。作为开发者,这时必须定义自己的Handler,并且实现ChannelActive函数,因为这是从底层到应用的数据,这就是平时我们在编写服务器端的代码时,都会定义一个继承InboundHandler的handler,并且覆盖channelActive函数的原因。

      4、总结

      本文分析了ChannelPipeline对Handler的管理过程,它的主要思路是利用ChannelHandlerContext上下文获取Handler,然后间接调用Handler的函数实现处理逻辑。