channelHandler 在Netty 4.x版本有了相當大的改動
http://netty.io/wiki/new-and-noteworthy.html 官網的更新改進說明。
以下節選官網更新說明的部分中文翻譯:
“
在3.x時代,所有的I/O操作都會創建一個新的ChannelEvent對象。對每個讀或寫的操作,還會額外創建一個新的ChannelBuffer對象。由於將資源管理和buffer的池化交給了JVM,這實際上極大地簡化了Netty的內部實現。但是,基於Netty開發的應用在高負載下運行時,有時會觀察到GC(Garbage Collection)的壓力增大或變化不定,這些問題的根源也來自於這里。
4.0通過把事件對象替換為直接與類型相對應(譯者注:原文為strongly typed,但是我覺得直譯為強類型不太容易理解)的方法調用,幾乎完全避免了事件對象的創建。3.x中,有類似於handleUpstream()和handleDownstream()這種能夠捕獲所有相關類型事件的處理器方法,4.0中你將不會再看到它們的身影了。所有的事件類型現在都有各自對應的處理器方法:
“
”所有這些變化意味着用戶無法去擴展ChannelEvent這個已經不存在的接口了。那用戶要怎樣才能定義他或她自己的事件類型呢,就像IdleStateEvent?4.0中的ChannelHandler有一個處理器方法叫做userEventTriggered(),它就是被設計用來滿足這種特殊的用戶需求。
“
4.x版本中簡化了channel 狀態模型(Simplified channel state model):
3.x版本的:

在4.x版本中:
ChannelOpen ChannelBound 和ChannelConnected 合並到ChannelActive.ChannelDisconnected ChannelUnbound ChannlClosed合並到ChannelInactive中
如下圖所示:

在Netty4.0.12的源代碼中我們可以看到AbstractChannel中的:
AbstractUnsafe{
...//調用fireChannelActive()
private void register0(ChannelPromise promise)
public final void bind(final SocketAddress localAddress, final ChannelPromise promise)
...//調用fireChannelInactive()
public final void disconnect(final ChannelPromise promise)
public final void close(final ChannelPromise promise)
}
..值得注意的是官網還特意提示了ChannelRegister和ChannelOpen和ChannelClosed有很大的區別
引入翻譯:"channelRegistered和channelUnregistered這兩個事件與channelOpen和channelClosed具有的意義是不一樣的。它們(channelRegistered和channelUnregistered)是在支持Channel的動態注冊、注銷以及再注冊時被引入的"

如圖所示。注冊和注銷僅僅用於每次的操作。
以下是個人口水:
貌似這么做的好處在於。把channel的異常放在一個方法內統一處理。在3.x的開發過程中發現。很多時候我們想要的只是一個結果。服務端數據在客戶端channel斷開連接。解綁定。關閉3中狀態時,需要將相對應的信息數據處理掉。在4.x版本中將這三個事件整合之后。只需要統一的處理就好了。
1 // 管道從不活躍狀態 轉到 活躍狀態 觸發 2 @Override 3 public void channelActive(ChannelHandlerContext ctx) throws Exception { 4 final Channel channel = ctx.channel(); 5 if(channel.isOpen()){ 6 // 管道 活躍的 並且是開啟狀態 7 } 8 super.channelActive(ctx); 9 } 10 11 // 管道從活躍狀態 轉到 不活躍狀態 觸發 12 @Override 13 public void channelInactive(ChannelHandlerContext ctx) throws Exception { 14 15 Channel channel = ctx.channel(); 16 if(!channel.isOpen()){ 17 18 19 } 20 super.channelInactive(ctx); 21 }
