【曹工雜談】Maven IOC容器的下半場:Google Guice

前言

在前面的文章里,Maven底層容器Plexus Container的前世今生,一代芳華終落幕怀各,我們提到幅垮,在Plexus Container退任后岭接,取而代之的底層容器是Guice冕末。

Guice的應(yīng)用也還比較廣泛,以下輪子中(僅部分)都有它活躍的身影:

  • google內(nèi)部
  • scalatest
  • TestNG
  • Caffeine Cache
  • Spring Security Config
  • elastic search
  • jenkins

這很多輪子,都是直接用的Guice坟乾,那是因為沒什么歷史包袱迹辐;但Maven不一樣,maven之前用自己的IOC輪子甚侣,有自己獨特的定義組件的方式(比如Spring通過@Component注解來定義)明吩;但是Guice作為一個獨立的IOC框架,那肯定是不認(rèn)識Maven中的組件的殷费。

因此印荔,這中間肯定需要兼容啊,Maven的組件详羡,還是用的Plexus IOC容器那套方式去定義仍律,但是他們開發(fā)了一個中間層,把那些組件解析后实柠,存放到了Guice容器中水泉。

這里說,把組件解析后窒盐,存放到了Guice容器中草则,這個也不是特別準(zhǔn)確,更準(zhǔn)確的說法是蟹漓,放到了基于Guice進(jìn)行了一層封裝的一個容器中畔师,這個容器叫做:sisu,由eclipse在維護(hù)這個開源項目(https://www.eclipse.org/sisu/)牧牢。

可能你就疑惑了,就一個破IOC姿锭,搞得多有技術(shù)含量一樣塔鳍,還一層套一層。呻此。這個我們就先不管了轮纫,這期我先講Guice,然后大家就懂了焚鲜,為啥Sisu要要封裝一層了掌唾。總結(jié)一下忿磅,依賴路徑是:

最底層的是google Guice --》 sisu(eclipse)--》 sisu-plexus兼容層--》plexus --》maven糯彬。

好了,開始正文葱她。

Guice是什么

根據(jù)wiki的描述撩扒,Guice就是依賴注入框架,由google開源吨些。主要特點就是:支持以java注解的方式配置組件及依賴搓谆。最早的版本應(yīng)該是在2007年炒辉,我還找到一篇當(dāng)年的報道 https://developers.googleblog.com/2007/03/

當(dāng)時還是2007年泉手,而2004年的時候黔寇,支持注解的JDK1.5才放出來,與此同時斩萌,Spring早期版本主要也還是以xml配置為主缝裤,Guice在那時就支持全注解配置,以當(dāng)時的眼光來看术裸,很前沿了倘是。

接下來,我們就來仔細(xì)了解下Guice的用法袭艺。

核心理念

在開始講之前搀崭,我說下我對IOC框架的理解先。很多時候猾编,可以簡單地說瘤睹,IOC容器是一個map,一個放東西的地方答倡,就像一個中藥房轰传,每個格子里會放一種藥材,而每個格子上瘪撇,有一個標(biāo)簽获茬,來說明里面放的是什么藥材。

既然是放東西的地方倔既,核心就是兩個部分恕曲,怎么放,放的時候渤涌,可能就要考慮到后續(xù)怎么找的問題佩谣。比如,如果你打算只支持根據(jù)物品的類型來找实蓬,那你要考慮到:如果這個類型的物品有多個茸俭,要怎么辦?怎么區(qū)分這多個物品安皱?

如果你打算解決這個問題调鬓,那你可能就會想:那我放的時候,再給這些物品取個名字吧酌伊,免得多個相同類型的物品袖迎,分不清。

甚至呢,你可能會考慮燕锥,物品的權(quán)限隔離辜贵,比如,物品上再加個存放人的字段归形,以后取得時候托慨,就只能:自己取自己的,不能取別人的暇榴。

反正厚棵,最終還是看需求,一般來說蔼紧,像我們spring這種婆硬,按類型就差不多了,一個類型多個實現(xiàn)的時候奸例,再根據(jù)名字區(qū)分一下就ok彬犯。

而Guice呢,我這邊會重點講解:怎么存查吊。至于取谐区,可能還分成兩種,依賴注入和直接從容器中取逻卖。但是依賴注入的底層實現(xiàn)宋列,也是:發(fā)現(xiàn)我依賴的某個東西沒有,就去容器里取评也。

所以炼杖,取東西,我們只需要關(guān)注:直接從容器中怎么獲取就行盗迟;我這邊就不會特別關(guān)注依賴注入的問題嘹叫。

Guice中,存東西的多種方式

概覽

存東西诈乒,在Guice的文檔里,名詞叫做Binding婆芦,中文就是綁定吧怕磨。

https://github.com/google/guice/wiki/Bindings

綁定是什么意思,就是我最終可能需要從容器中獲取ClassA類型的對象消约。既然要取肠鲫,那還得先存,存的時候或粮,我就要建立綁定:ClassA --》該Class類型對象的獲取方式导饲。

其實還是很簡單的。下邊就跟著我的代碼例子,我們來看看渣锦。

以下全部的代碼硝岗,都在:

https://gitee.com/ckl111/maven-3.8.1-source-learn/tree/master/my-test-modules/official-guice-demo

1. linkedbinding-綁定接口到實現(xiàn)類

先來一個接口和實現(xiàn):

public interface HelloInterface {
    void hello();
}
public class HelloInterfaceImpl implements HelloInterface {
    @Override
    public void hello() {
        System.out.println("hello world");
    }
}

再來看看,怎么放到容器袋毙,和簡單的從容器中取出來的方法:

大家看我代碼截圖型檀,放東西的時候,就是要指定這個接口听盖,對應(yīng)的實現(xiàn)類胀溺。

取東西的時候,再去根據(jù)接口取就行了皆看。

2.BindingAnnotations 一個類型有多個實現(xiàn)類的時候的綁定方式

接口和多個實現(xiàn)類:

interface HelloInterface {
    void hello();
}
class HelloInterfaceImpl implements HelloInterface {

    @Override
    public void hello() {
        System.out.println("hello world");
    }
}

class HelloInterfaceImpl2 implements HelloInterface {

    @Override
    public void hello() {
        System.out.println("hello world");
    }
}

如果我們還是按前面的辦法去取仓坞,框架就暈圈了,多個實現(xiàn)類腰吟,我給你哪一個呢无埃?麻煩再明確一下吧,ok嗎

Guice有個注解蝎困,叫Named录语,可以加在各種地方,注解本身禾乘,支持設(shè)置名稱澎埠。

這里意思就是說,你接口不是多個實現(xiàn)嗎始藕,那我們這樣:接口+注解蒲稳,才算是唯一的key,這樣ok了吧伍派。

因此江耀,現(xiàn)在就變成了這樣:接口+注解1 --》 實現(xiàn)類1;接口 + 注解2 --》 實現(xiàn)類2.

那我怎么取呢诉植?簡單啊祥国,怎么存,怎么取晾腔,存的時候舌稀,用的接口+注解,取的時候灼擂,也需要這樣壁查。

既然,可以用官方的Named注解剔应,那其實自己的注解也一樣可以用睡腿。

3. InstanceBindings 接口直接綁定一個單例對象

如果同一個類型语御,要綁定到多個實例的情況,同前面的處理方式一樣席怪。

4. 綁定到工廠方法:授人以魚不如授人以漁

前面都是些直來直去的辦法应闯,這次不一樣,我只告訴你何恶,這個東西的獲得方法孽锥。

5. 不用接口了,直接綁定一個實現(xiàn)類

前面都是根據(jù)一個接口類细层,去取接口對應(yīng)的實現(xiàn)之類的惜辑。這次不一樣,直接就是一個實現(xiàn)類了疫赎。

public class UtilService {
}

像上面這個情況盛撑,那肯定是直接調(diào)用這個類的構(gòu)造函數(shù)了。

6. 接口綁定到一個構(gòu)造函數(shù):ToConstructorBindings

哎捧搞,我是越來越無語了抵卫,Guice的騷操作真是多啊。

7. 內(nèi)置的不用綁就能用的

主要有:Logger胎撇、Injector本身(就是相當(dāng)于可以幫你注入容器自身)

8. 能不能不綁定直接用

用慣了spring的我們介粘,現(xiàn)在已經(jīng)是不需要這么綁來綁去了。我們看看Guice的支持怎么樣

不綁定的話晚树,可以這樣:

@ImplementedBy(TestInterfaceImpl.class)
interface TestInterface {
}

這就相當(dāng)于姻采,你要自己指定一下,你的實現(xiàn)類是誰爵憎,或者你的provider是誰慨亲。但是官方不建議用這種隱式綁定,不知道為啥宝鼓,還出了個選項刑棵,專門禁用隱式綁定。

9. 一個接口多個實現(xiàn)類愚铡,一次性全獲取回來

這個場景蛉签,就是一次性把多實現(xiàn)類一把取回來,放到一個集合里給你沥寥。

這個場景我沒寫代碼碍舍,大家自己看一下文檔,也簡單营曼。

10. 注入的方式

前面說了很多怎么手動從容器里面取,當(dāng)然了愚隧,要自動注入的話蒂阱,也是支持:構(gòu)造器注入锻全、field注入等等方式。

如以下為構(gòu)造器注入:

其他支持的特性

其他的录煤,比如循環(huán)依賴鳄厌、aop也是大體支持的,只是這個容器在安卓端用妈踊,會有問題了嚎,因為aop好像不太支持,所以給安卓端還專供了一個去掉aop的版本廊营。

循環(huán)依賴之類的歪泳,具體實現(xiàn)還沒怎么看過。

另外露筒,guice默認(rèn)生成的是多例(類比spring的prototype呐伞,而不是singleton),但是本身也是支持singleton的慎式,我前面的代碼例子有伶氢。

最大槽點

可以看出,Guice是很輕量瘪吏,輕量的意思是癣防,功能沒Spring那么全,所以掌眠,我們還需要去顯式地:配置每個接口蕾盯,要怎么獲取它的對象(方法也是五花八門,哈哈哈扇救,如前面展示的)刑枝。

當(dāng)然,配置ok后迅腔,我們獲取某對象的時候装畅,它會幫我們?nèi)ネ瓿勺詣幼⑷氲臇|西。

但是沧烈,它也不支持類路徑掃描啊掠兄,比如給個包名,自動去掃描這個包下面的組件锌雀,反正官方不支持蚂夕,說是有第三方插件,還沒試過腋逆。

總結(jié)

在各種輪子里婿牍,用來管理自己的代碼間的相互依賴,用Guice確實足夠了惩歉,用在業(yè)務(wù)代碼等脂,就還是有點累俏蛮。

因為,主要是:各種依賴要自己配上遥,只是集中在一個地方配置而已搏屑,沒有像spring那樣,約定通過接口找對象時粉楚,默認(rèn)就是找實現(xiàn)類辣恋,然后反射生成對象。

這一點來說模软,確實是:約定優(yōu)于配置伟骨,就像Maven為啥打敗了ant,也是這個道理撵摆。

另外的問題就是底靠,不支持spring的那種component-scan。

基于這兩個問題呢特铝,方法肯定是有的暑中,所以,Maven也足夠聰明鲫剿,沒有直接基于Guice鳄逾,而是選擇了基于Guice封裝后的Sisu,而Sisu就可以解決我們說的問題灵莲,支持類路徑掃描之類的雕凹。

我們看看sisu怎么介紹自己:

就是比Guice多了些看起來還很不錯的、Spring早已有了的特性吧政冻∶兜郑回頭我們肯定要再介紹sisu的。

再見明场,以上汽摹。

本文由博客一文多發(fā)平臺 OpenWrite 發(fā)布!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末苦锨,一起剝皮案震驚了整個濱河市逼泣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌舟舒,老刑警劉巖拉庶,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異秃励,居然都是意外死亡是嗜,警方通過查閱死者的電腦和手機(jī)浑测,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門霹陡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人帚稠,你說我怎么就攤上這事〈布眩” “怎么了?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵榄审,是天一觀的道長砌们。 經(jīng)常有香客問我,道長搁进,這世上最難降的妖魔是什么浪感? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮饼问,結(jié)果婚禮上影兽,老公的妹妹穿的比我還像新娘。我一直安慰自己莱革,他們只是感情好峻堰,可當(dāng)我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著盅视,像睡著了一般捐名。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上闹击,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天镶蹋,我揣著相機(jī)與錄音,去河邊找鬼赏半。 笑死贺归,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的断箫。 我是一名探鬼主播拂酣,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼瑰枫!你這毒婦竟也來了踱葛?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤光坝,失蹤者是張志新(化名)和其女友劉穎尸诽,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體盯另,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡性含,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了鸳惯。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片商蕴。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡叠萍,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出绪商,到底是詐尸還是另有隱情苛谷,我是刑警寧澤,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布格郁,位于F島的核電站腹殿,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏例书。R本人自食惡果不足惜锣尉,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望决采。 院中可真熱鬧自沧,春花似錦、人聲如沸树瞭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽晒喷。三九已至旺嬉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間厨埋,已是汗流浹背邪媳。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留荡陷,地道東北人雨效。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像废赞,于是被迫代替她去往敵國和親徽龟。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容