最近一直在看 Mina的源碼,用了Mina這么長(zhǎng)時(shí)間,說(shuō)實(shí)話,現(xiàn)在才開(kāi)始對(duì)Mina有了一些深刻的理解,關(guān)于Mina的基本知識(shí)的介紹,這里就不多說(shuō)了,網(wǎng)上已經(jīng)有 很多不錯(cuò)的文章都對(duì)Mina做了較深刻的剖析,現(xiàn)在就是想從Mina的最根本的地方來(lái)對(duì)Mina做一些深層次上的探討。

 

還是先從Mina的入口程序來(lái)說(shuō),每當(dāng)要啟動(dòng)一個(gè)Mina的程序(包括服務(wù)器和 客戶端)時(shí)候,這里只是對(duì)服務(wù)器重點(diǎn)做一些講解,至于說(shuō)Mina的客戶端的應(yīng)用,這里只是簡(jiǎn)單的涉及一點(diǎn),不會(huì)對(duì)其做很深入的探討。但是Mina的服務(wù)器 和客戶端在很大的程度上都是一樣,所以這里就“掛一漏萬(wàn)”的簡(jiǎn)單講解一下。

 

在此之前我一直想找一種“串糖葫蘆”的方式來(lái)講解一下Mina,可是一直沒(méi)有時(shí) 間來(lái)看Mina的源碼,真的是無(wú)從下手,雖然網(wǎng)上的很多關(guān)于Mina的一些文章,講解的非常透徹了,但是可能對(duì)于初學(xué)者來(lái)說(shuō),顯得有些深?yuàn)W,在這里特別的 提一下洞庭散人對(duì)Mina源碼的透徹的分析,如果你對(duì)Mina已經(jīng)有了一定的了解或者是正在學(xué)習(xí)Mina的源碼,建議你去看看他的博客,里面有很多東西講 的是相當(dāng)?shù)轿坏?。在這里就不在多舉例子了。寫這篇文檔主要是想對(duì)剛接觸Mina的人講解一些Mina的基本知識(shí),由淺入深,一步一步的學(xué)習(xí)Mina思想的 精髓,我接觸Mina的時(shí)間也比較長(zhǎng)了,幾乎天天在和它打交道,每當(dāng)你發(fā)現(xiàn)一個(gè)新奇的用法的時(shí)候,你真的會(huì)被Mina所折服,我這里不是對(duì)Mina的吹 捧,記得我曾經(jīng)和同事開(kāi)玩笑說(shuō),“等真正的懂得了Mina,你就知道什么叫Java了”,所以,我現(xiàn)在想急切的把現(xiàn)在所知道和了解的所有關(guān)于Mina的一 些東西都想在這篇文章里面寫出來(lái),如果有寫的不到位的地方還請(qǐng)各位同學(xué)多多指正,下面就開(kāi)始對(duì)Mina做一個(gè)完整的介

紹。

 

先說(shuō)說(shuō)Mina的幾個(gè)類和接口
(1) IoService
(2) BaseIoService
(3) BaseIoAcceptor
(4) IoAcceptor
(5) IoConnector

這幾個(gè)類和接口是整個(gè)服務(wù)器或客戶端程序(IoConnector)的入口程序,其中就Mina的整體上來(lái)說(shuō),IoService是所有IO通信的入口程序,下面的幾個(gè)接口和類都是繼承或者實(shí)現(xiàn)了IoService接口。

 


下面先給出Mina(入口程序)的整體架構(gòu)圖:

                                                                Mina的整體架構(gòu)圖

 

在這里先提出幾個(gè)個(gè)問(wèn)題:
(1)為什么有了一個(gè)IoService還要再有一個(gè)BaseIoService?
(2)BaseIoService和IoAcceptor(IoConnector)有什么區(qū)別?
(3)BaseIoAcceptor(BaseIoConnector)為什么不去直接實(shí)現(xiàn)IoService,而是又添加了

        IoAcceptor(IoConnector)?
   
帶著這幾個(gè)問(wèn)題我們來(lái)解讀一下Mina的源碼:
首 先,解答第一個(gè)問(wèn)題,為什么有了一個(gè)IoService還要再有一個(gè)BaseIoService?IoService和BaseIoService最明顯 的區(qū)別就是IoService是一個(gè)接口,而B(niǎo)aseIoService是一個(gè)抽象類。BaseIoService實(shí)現(xiàn)了IoService中的部分方 法。

 

這里先把IoService接口中要實(shí)現(xiàn)的方法和BaseIoService中實(shí)現(xiàn)的方法列舉如下:

 

 



 

通過(guò)對(duì)IoService和BaseIoService的比較可以發(fā)現(xiàn),除了 getDefaultConfig()這個(gè)方法沒(méi)有在BaseIoService中實(shí)現(xiàn)之外,其他的方法都已經(jīng)在BaseIoService實(shí)現(xiàn)了。這里 就有一個(gè)問(wèn)題,為什么BaseIoService只是實(shí)現(xiàn)了IoService的部分方法,而沒(méi)有全部實(shí)現(xiàn)IoService的方法呢?通常都知道,接口 中的方法是必須要由實(shí)現(xiàn)類來(lái)實(shí)現(xiàn)的,這點(diǎn)是毋庸置疑的。你可以寫一個(gè)空方法,里面沒(méi)有任何的邏輯處理,但是你的實(shí)現(xiàn)類中卻不能沒(méi)有該方法。但是在Mina 中作為實(shí)現(xiàn)類的BaseIoService卻沒(méi)有IoService指定的方法getDefaultConfig(),難道Mina真的有獨(dú)到之處?不 是!仔細(xì)看看

BaseIoService你就會(huì)知道,BaseIoService是一個(gè)抽象 類,抽象類就是用來(lái)被繼承的,它提供了一些其子類公用的一些方法,當(dāng)抽象類實(shí)現(xiàn)一個(gè)接口時(shí),抽象類可以有選擇性的實(shí)現(xiàn)其所有子類都需要的實(shí)現(xiàn)的一些方法, 對(duì)于接口中指定法方法,抽象類可以選擇全部實(shí)現(xiàn)或者部分實(shí)現(xiàn)。在Mina中如果沒(méi)有BaseIoService這個(gè)抽象類,而是由 BaseIoAcceptor和BaseIoConnector直接去實(shí)現(xiàn)BaseIoService接口,那么必然會(huì)導(dǎo)致這個(gè)兩個(gè)實(shí)現(xiàn)類中都要重寫相應(yīng) 的方法,這樣就脫離了面向?qū)ο笤O(shè)計(jì)的本質(zhì),沒(méi)有達(dá)到復(fù)用的目的。在BaseIoAcceptor/BaseIoConnector和 BaseIoService之間添加一個(gè)BaseIoService就是為了達(dá)到代碼復(fù)用的目的。在這個(gè)問(wèn)題上主要是要記住兩點(diǎn):
  
   1)抽象類在實(shí)現(xiàn)接口的時(shí)候可以部分或者全部實(shí)現(xiàn)接口中的方法。但是當(dāng)抽象類只是實(shí) 
       現(xiàn)了接口中的部分方法的時(shí)候,抽象類的子類必須要實(shí)現(xiàn)抽象類中未實(shí)現(xiàn)的接口的方
       法。在此處,IoService的getDefaultConfig()方法在BaseIoService(BaseIoAcceptor  
       是BaseIoService的子類,但它也是一個(gè)抽象類,所以它也沒(méi)有實(shí)現(xiàn)getDefaultConfig()),

       getDefaultConfig() 是    由BaseIoAcceptor的子類們來(lái)實(shí)現(xiàn)的(如SocketAcceptor,這是一個(gè)

       具體實(shí)現(xiàn)類)。所以接口的所有方法必須被具體的實(shí)現(xiàn)類實(shí)現(xiàn)和抽象類在實(shí)現(xiàn)接口的時(shí)候可以部分

       或者全部實(shí)現(xiàn)接口中的方法是不矛盾的。

 

   2)注意代碼的重用。在面向?qū)ο蟮木幊陶Z(yǔ)言中都提供了抽象類和接口,抽象類和接口最大的區(qū)別

        就是抽象類提供了方法的具體實(shí)現(xiàn),供其子類來(lái)調(diào)用;而接口只是提供了對(duì)方法的聲明,其方

        法的實(shí)現(xiàn)要由其具體實(shí)現(xiàn)類來(lái)做。在Java中一個(gè)子類只能有一個(gè)父類,但是卻能實(shí)現(xiàn)多個(gè)接口。

       個(gè)人認(rèn)為接口和抽象類各有特色,接口的使用比較靈活,不同的接口可以讓其子類扮演不同的角

       色,側(cè)重于類的復(fù)用,在很大程度上解決了代碼復(fù)用的問(wèn)題;抽象類更側(cè)重的是方法的復(fù)用,某

       種意義上講,抽象類的使用對(duì)于程序來(lái)說(shuō)使用起來(lái)更加輕松,但是是使用抽象類還是接口要根據(jù)

       具體的情況而定。


      對(duì)于接口和抽象類的具體的用法請(qǐng)參考閆宏的《Java與模式》中相關(guān)部分的講解。

 

之所以在這里羅列這么些問(wèn)題,目的不僅僅是為了講解Mina的原理,而是想從一 個(gè)高的角度來(lái)看待的這個(gè)經(jīng)典的開(kāi)源項(xiàng)目,通過(guò)對(duì)Mina的學(xué)習(xí)和理解,能夠真正的懂得什么是一個(gè)項(xiàng)目,什么是面向?qū)ο缶幊蹋举|(zhì)的東西是怎么靈活運(yùn)用 Java來(lái)達(dá)到上面的兩個(gè)目的。這個(gè)才是最重要的,哪怕是你在看完本文后對(duì)Mina的理解還是有點(diǎn)模糊,但是你至少要知道在編寫一個(gè)程序的時(shí)候怎樣從面向 對(duì)象的角度上去思考一個(gè)問(wèn)題,而不是在用著面向?qū)ο蟮恼Z(yǔ)言寫著結(jié)構(gòu)化的程序。這些東西都是自己做開(kāi)發(fā)這么長(zhǎng)時(shí)間的一些心得,在這里總結(jié)出來(lái),目的主要是用 于交流和學(xué)習(xí),不是在賣弄,只是想讓更多的初學(xué)者少走一些彎路,懂得學(xué)習(xí)的方法。

 

還是回到對(duì)Mina的剛提出的那幾個(gè)問(wèn)題上來(lái),現(xiàn)在,第一個(gè)問(wèn)題已經(jīng)解決了,為什么有了一個(gè)IoService還要再有一個(gè)BaseIoService?答案就是為了代碼的復(fù)用。

 

其次,下面開(kāi)始討論第二個(gè)問(wèn)題,BaseIoService和IoAcceptor(IoConnector)有什么區(qū)別?
在討論這個(gè)問(wèn)題之前,還是先給出這兩個(gè)類(接口)提供的方法,如下圖:


      

                                                                                               

在討論第一個(gè)問(wèn)題的時(shí)候我們已經(jīng)看過(guò)了BaseIoService的方法了,但是沒(méi)有對(duì)這些方法的功能做些梳理,現(xiàn)在就對(duì)這些方法做些簡(jiǎn)單的介紹:

 

getFilterChainBuilder() 和setFilterChainBuilder():這兩個(gè)方法主要是對(duì)一個(gè)服務(wù)的IoFilter的操作,關(guān)于IoFilter的詳細(xì)介紹會(huì)在后面給 出,現(xiàn)在你可以將其理解為是一個(gè)處理業(yè)務(wù)邏輯的模塊,例如:黑名單的處理、數(shù)據(jù)的轉(zhuǎn)換、日志信息的處理等等都可以在這個(gè)IoFilter中實(shí)現(xiàn),它的工作 原理和Servlet中的過(guò)濾器很相似。

 

addListener()和removeListener():這兩個(gè)方法通過(guò)名字看就可以理解了,就是給當(dāng)前的服務(wù)添加和刪除一個(gè)監(jiān)聽(tīng)器,這個(gè)監(jiān)聽(tīng)器主要是用于對(duì)當(dāng)前連接到服務(wù)的IoSession進(jìn)行管理,這個(gè)也會(huì)在后面做詳細(xì)的講解。

 

getManagerServiceAddress() 和getManagerSessions():這兩個(gè)方法的功能比較相似,一個(gè)是獲取當(dāng)前服務(wù)所管理的遠(yuǎn)程地址,一個(gè)是獲取當(dāng)前服務(wù)所管理的會(huì)話 IoSession,IoSession對(duì)SocketAddress做了一個(gè)完整的封裝,你也

可以先將這兩個(gè)方法的功能理解為是一回事,具體的區(qū)別會(huì)在后面給出。isManaged():檢測(cè)某個(gè)SocketAddress是否處于被管理的狀態(tài)。

 

getListeners():獲取當(dāng)前服務(wù)的監(jiān)聽(tīng)器。

 

看了上面對(duì)BaseIoService功能的介紹,現(xiàn)在我們可以理解 BaseIoService提供的方法主要是用于對(duì)當(dāng)前服務(wù)的管理。那么要管理一個(gè)服務(wù),前提條件是這個(gè)服務(wù)必須存在,存在的前提是什么,就是要啟動(dòng)一個(gè) 服務(wù),或者是連接到一個(gè)遠(yuǎn)程主機(jī)上,這兩個(gè)任務(wù)分別是IoAcceptor和IoConnector來(lái)完成的,此處要注意的是這兩個(gè)對(duì)象都是接口,沒(méi)有具 體的實(shí)現(xiàn),具體的實(shí)現(xiàn)會(huì)由下面介紹的它們相關(guān)的子類(SocketAcceptor等)來(lái)實(shí)現(xiàn)。這樣IoAcceptor/IoConnector的功能 我們就可以總結(jié)出來(lái)了,就是啟動(dòng)和停止一個(gè)服務(wù)。

 

對(duì)于一個(gè)完整的服務(wù)來(lái)說(shuō),既要有啟動(dòng)這樣的前提條件,還要有對(duì)服務(wù)的管理和對(duì)服 務(wù)響應(yīng)的邏輯處理,這兩個(gè)缺一不可,回到第二個(gè)問(wèn)題,BaseIoService和IoAcceptor(IoConnector)有什么區(qū)別?區(qū)別就在 于它們實(shí)現(xiàn)的功能不一樣,但都是為了一個(gè)完整的服務(wù)來(lái)打基礎(chǔ)的,兩者缺一都不能稱為一個(gè)完整的服務(wù)。這三個(gè)都是IoService子類(子接 口),oService只是提供了一些服務(wù)應(yīng)該具有多基本的方法,BaseIoService提供了IoService部分方法的具體實(shí)現(xiàn),而 IoAcceptor(IoConnector)是對(duì)特定服務(wù)要具備的操作的做了一些擴(kuò)展,這樣一個(gè)服務(wù)完整的模型正在逐漸向我們清晰的展現(xiàn)出來(lái)。

 

再次,討論一下第三個(gè)問(wèn)題。 BaseIoAcceptor(BaseIoConnector)為什么不去直接實(shí)現(xiàn)IoService,而是又添加了 IoAcceptor(IoConnector)?這個(gè)問(wèn)題其實(shí)在上面已經(jīng)有所涉及,為了達(dá)到對(duì)象復(fù)用的目的,所以Mina的設(shè)計(jì)者給出了一個(gè) BaseIoService,IoAcceptor(IoConnector)是實(shí)現(xiàn)一個(gè)特定服務(wù)必須要提供的一些方法。更具體一 點(diǎn),IoAcceptor(IoConnector)是為了一個(gè)特定的服務(wù)(服務(wù)器/客戶端)而設(shè)計(jì)的,而IoService只是提供了一個(gè)服務(wù)應(yīng)該具備 的一些基本的方法。所以在Mina中給出了一個(gè)針對(duì)具體服務(wù)的一個(gè)接口IoAcceptor(IoConnector),這樣 BaseIoAcceptor(BaseIoConnector)就提供了一個(gè)服務(wù)所必備的一些條件。因?yàn)樗磳?shí)現(xiàn)了 IoAcceptor(IoConnector)接口又繼承了抽象類BaseIoService,這樣就實(shí)現(xiàn)了IoService中的所有方法,并且也添 加了特定服務(wù)應(yīng)該具有的方法(即IoAcceptor(IoConnector)中的方法)。以上就是第三個(gè)問(wèn)題的答案。

 

 

 

Mina中提供的幾個(gè)特定的服務(wù)
從上面的討論中我們已經(jīng)知道了Mina上層的類和接口的一些功能。即圖中所示的已經(jīng)在上面解釋清楚了。



 在此我們可以把Mina的上層結(jié)構(gòu)簡(jiǎn)單的定義為Mina的“抽象層”,既然有了抽象層,肯定就會(huì)有其具體實(shí)現(xiàn),抽象中最重要的兩個(gè)類是BaseIoAcceptor和BaseIoConnector,它們分別是用于服務(wù)器和客戶端的一個(gè)入口程序。

首先,說(shuō)一下BaseIoAcceptor中的三個(gè)具體實(shí)現(xiàn)類:


DatagramAcceptorDelegate:數(shù)據(jù)報(bào)UDP通信的服務(wù)器入口程序。該類使用UDP協(xié)   議進(jìn)行通信,UDP協(xié)議主要是用在視頻、遠(yuǎn)程服務(wù)的監(jiān)聽(tīng)(如心跳程序)中等數(shù)據(jù)傳輸   要求不是很高的地方。
VmPipeAcceptor:虛擬通道(VM)通信的服務(wù)器入口程序。虛擬管道協(xié)議主要用于無(wú)線通信方面。             
SocketAcceptor:TCP/IP通信的服務(wù)器入口程序。這個(gè)是比較常用的協(xié)議,該協(xié)議主要   數(shù)據(jù)傳輸要求較高的地方,比如實(shí)時(shí)系統(tǒng)、游戲服務(wù)器等。


BaseIoAcceptor及其子類
與BaseIoAcceptor相對(duì)應(yīng)的就是BaseIoConnector,該類主要用于客戶端程序。其具體的子類就不再贅述,這里只給出BaseIoConnector及其子類的結(jié)構(gòu)圖。


BaseIoConnector及其子類

關(guān)于SocketAcceptor、IoFilter、IoProcessor、IoHandler等會(huì)有專門的文章來(lái)討論。這里就不在對(duì)這些組件類做詳細(xì)的說(shuō)明了。

標(biāo)簽: mina