天天看點

扒掉蕃薯的内褲-深入剖析J2Cache

最近看到蕃薯的j2cache強大到不行,居然長期占據開源中國開源項目排行榜,偶就氣不打一處來。

話說你是開源中國第一帥,這個咱們大家有共識,确實實力在那裡,我們都認了。

話說你口才比@永和 好,這個隻要永和沒有意見,我們也同意。

但是,做個j2cache居然還懸賞好多次,貌似要打造成開源中國第一開源項目,這就有點過分了。不對,不是過分,是相當過分。

是以今天,偶就狠狠的扒掉@蕃薯 的内褲,對j2cache進行一下深入剖析。

前面寫過一篇文章,标題是吐槽一下j2cache,吐槽過後發現j2cache的熱度居然火速上升,貌似有成為開源中國第一開源項目的意思,偶這小心髒就有點受不了了,于是決定再寫一篇文章,直接狠一點把@蕃薯 的内褲扒掉,對j2cache進行一下深入剖析。

這個沒有什麼問題,不管誰來做,大緻也是這個樣子的,是以到這裡來說,還是非常不錯的。

但是實際上也有改進的餘地,比如把cache換成cache,這樣

就可以變成:

這樣有個好處,就是可以避免大量的強制類型轉換,另外對于不支援object類型的緩沖架構來說,就可以檔案的實作類中如下實作:

而不用加大量的類型強力轉,當然這裡是個細節問題。

它的内容如下:

這個類,從作者的本意來說是增加了一個描述所處理緩沖對象的所在級别及區域相關的對象,但是我感覺,這個類是完全不必要的,而且正是由于它的存在導緻後續圍繞它的處理都是不必要的。

那麼我們來看看它是怎麼被使用的:

在j2hibernatecache類中

看到沒,前面折騰了半天,還是把cacheobject中的value屬性搞出來的,這不是脫褲子放屁,多了一次手續麼?

我們來搜尋一下使用cacheobject類的地方:

扒掉蕃薯的内褲-深入剖析J2Cache

目光所及,點進去看,居然沒有看到什麼特别的地方,是以問題依然是:這個類有存在的必要麼?

這個時候又看到一個接口,叫cachechannel,内容如下:

這個接口,就有點疑問,如果說它隻是一個通道的話,為什麼它還有與緩沖相關的get和set方法?在這裡,可以看到它的許多方法都增加了region的參數,表明它是支援區域的一些緩沖處理。

另外看到close方法的時候,感覺這個接口的設定可能定位有改進的餘地,因為它把通道層的和緩沖相關的接口混在一個裡面了,表面看看問題不大,實際上在實作時會帶來一些不爽,同時可能會誘導開發人員做了不合理的實作。或許這個方法應該放在cacheprovider當中去?

這個類實際上就是個工廠類,用于建立cache執行個體,問題不大。

這個東東的出現就發現了随意之處,從類的名字看,應該是用來做測試的,但是它居然就出現在main/src下,但是也可以解釋為這個就是用來做測試的,也可以解釋得通,但是總還是有點怪怪的---這裡請允許我引用悠然的名言:好的設計是品出來的。不是說這麼做不可以,但是放在核心工程顯目位置就有點随意了。

同樣的還有command類,

這個類裡面也有一些随意之外,比如,産生随機數的算法:

如果做這個api的同學看到這麼使用的,幾乎會一口氣上不來的,合理的怎麼寫,請同學樣在後面回帖。

再比如:

這些個東東本來應該是在common類的工具類中的,結果也出現在這個類中。

這個類的許多算法,也比較奇葩,個人覺得不用這麼複雜,可以用更簡單的方式來實作。

這個就是著名的j2cache類了,簡單看來,存在如下問題:

第一、它是個單執行個體的類,也就是說無法啟動多個執行個體。但然也不能說這樣就不行,但是如果我的應用場景中需要在不同場景用不同的執行個體呢?就無法滿足了。

第二、它和具體的實作相關:

這個實作是非常不妥的實作,最起碼對于未來的擴充性、可變性方面都存在非常大的限制。

第三、命名的不合理性

本來從名字和定位來看,我覺得它應該是cache或cachechannel的一個實作類,結果發現它不是,它居然隻是起個工廠類作用的類。

第四、config的處理

config居然是由j2cache讀進來,然後讓别的類來擷取的,居然是這樣實作的???這會導緻非常嚴重的問題,依賴關系勢必出現混亂,實際上也會出現循環依賴的問題,當然@蕃薯 的解決方案就是都放在一個工程裡面,循環依賴的問題就沒有了,但是就會出現其它的問題,後續再來說明。

好的,上面就把j2cache應用根目錄中的内容都走馬觀花看了一遍,當然隻還隻算扒了一下外套,現在開始慢慢扒内褲。

我來看看看它的依賴樹:

上面是j2cache的依賴樹

可以看到,上面的工程裡面依賴了許許多多的包,這個時候就可能會引入大量的依賴沖突問題。另外,我隻想用你這個東東,為什麼還把hibernate引入了?

為什麼必須用ehcache,雖然ehcache非常不錯,但是如果把它變成可選件是可以接受的,變成必選件就要了命了。

同樣的,這裡面引入的許多内容從道理上都講不通,比如:

為什麼必須得是2.8,萬一我工程已經用其它版本了呢?如果高版本可以完全相容老版本還好說,如果不能完全相容,又怎麼辦??

當然有的同學又說了,“你覺得不好就别用,覺得好就用”,當然這是另外一個話題,和今天的話題不太相關,今天的任務是扒@蕃薯 内褲。

上一次我寫吐槽j2cache的時候,其實就有人說了,你吐槽了半天,然并卵,you can you up, no can no bb。話雖不太好聽,但是還是有點道理的。

今天我就說說如果是我來設計j2cache,那麼它是怎麼個樣子的。

其實所有的問題都是可以解決的,而這些問題的根源就在于設計和實作的不合理導緻的,那麼下面就來講講悠然版j2cache怎麼設計。

呵呵,繼續說一句悠然名言:你做得不夠好,是因為你分得不夠細。

工程一:cache接口設計

這個工程啥實作也沒有,就是一個cache的接口,用來規範cache通路規範,具體怎麼寫,不同人有不同的寫法。

工程二:

各種不同種類的cache實作,比如:ehcache,jedis,memcache,jcs,等等,如果精力過剩,各種版本的都來一個也可以。當然,實際上這裡每一個具體實作都是一個獨立的工程了。

工程三:

j2cache,它也是cache接口的一個實作類,在它裡面注入兩個cache執行個體,然後在處理邏輯上做兩級緩沖的處理。

當然,如果你想要弄個cachemanager也是可以的,這個不是關鍵因素,随便都可以。

最後就貼一下tiny自己的二級緩沖實作類:

這樣的作法,就會把一二級緩沖的實作安全分離出去,才不管它是具體是什麼技術實作的,給最終的使用人員以最大的自由度。

同時,由于每種不同的緩沖,基于不同的緩沖架構或版本,也可以有多個執行個體存在,使用者在使用的時候,也可以直接引用具體的緩沖實作就好,當然也可以自己根據接口實作一個就ok了,這樣避免了大量不需要的jar包的引入,對于工程化處理是非常有好處的。

開篇有講,要扒@蕃薯 的内褲,實際上就是要蕃薯把一切備援的東西都去去掉,隻留下光溜溜、赤裸裸的緩沖、二級緩沖,其它都作為擴充包由使用者選用或者自行擴充,這樣整體弄下來,就會是一個分離有度、協作良好、易于使用的j2cache架構。

附被扒了内褲的蕃薯真容:

扒掉蕃薯的内褲-深入剖析J2Cache