Dagger - 快速依賴注入器(for android and java) (1)

文章譯自dagger的官方說(shuō)明文檔, 不足之處歡迎指正!

引言

在程序中引瀑, 最重要的類是那些真正實(shí)現(xiàn)功能的類:比如BarcodeDecoder(條形碼解碼器),KoopaPhysicsEngine(某某引擎),AudioStreamer(音頻流)衔彻。這些類往往有些依賴類审磁, 比如BarcodeCameraFinder(條形碼圖形識(shí)別器),DefaultPhysicsEngine(默認(rèn)物理引擎), 和HttpStreamer(http輸出流).

相反啡浊, 程序中最不重要的類是輔助類(take up space without doing much at all): BarcodeDecoderFactory(條形碼解析器工廠), CameraServiceLoader(相機(jī)服務(wù)加載器), 和 MutableContextWrapper(易變環(huán)境變量包裝器).這些輔助類就像笨拙的膠帶一樣,將那些重要的功能類連接起來(lái)陶因。

Dagger 就是這些工廠類的終結(jié)者骡苞。 它幫助你專注在那些重要的功能類上。通過(guò)聲明依賴關(guān)系楷扬, 指定規(guī)則解幽, 構(gòu)建整個(gè)應(yīng)用程序。

Dagger 構(gòu)建在標(biāo)準(zhǔn)的javax.injectannotation基礎(chǔ)之上, 每一個(gè)類都很容易測(cè)試烘苹。你也不需要為了便于將 RpcCreditCardService 替換為 FakeCreditCardService亚铁, 而構(gòu)建一堆的樣板(boilerplate)。

依賴注入(Dependency injection)也并不是僅僅為了測(cè)試螟加。 它可以使很容易創(chuàng)建 可復(fù)用、通用的Module吞琐。在整個(gè)應(yīng)用程序中捆探, 你可以共享同一個(gè)AuthenticationModule。你也可以在開(kāi)發(fā)過(guò)程中使用DevLoggingModule, 而在發(fā)布時(shí)使用ProdLoggingModule站粟。

更多信息請(qǐng)移步watch an introductory talk by Jesse Wilson at QCon 2012.

譯者:

上文中有兩個(gè)概念:

1. 依賴注入黍图, Dependency injection. 也叫控制反轉(zhuǎn)(IoC), 就是通過(guò)一定的規(guī)則管理對(duì)象間的依賴關(guān)系奴烙。詳細(xì)概念參考wiki控制反轉(zhuǎn)

2. 而Dagger組件則通過(guò)annotation實(shí)現(xiàn)了依賴注入助被。

Using Dagger

接下來(lái), 我們通過(guò)構(gòu)建一個(gè)Coffer Maker 來(lái)說(shuō)明 依賴注入 和 Dagger切诀。你可以下載完整的Coffee Maker示例代碼揩环, 編譯調(diào)試。

聲明依賴關(guān)系

Dagger 構(gòu)造應(yīng)用程序的類對(duì)象幅虑,并組合其依賴關(guān)系丰滑。 Dagger使用javax.inject.Injectannotation 標(biāo)記那些構(gòu)造函數(shù)和成員變量需要依賴注入。

Dagger將使用@Inject 注釋的構(gòu)造函數(shù)創(chuàng)建類對(duì)象倒庵。 當(dāng)請(qǐng)求構(gòu)建新的類對(duì)象時(shí)褒墨, Dagger 將自動(dòng)獲取相應(yīng)的參數(shù)炫刷, 并調(diào)用構(gòu)造函數(shù)。

class ThermosiphonimplementsPump{

private final Heater heater;

@Inject

Thermosiphon(Heater heater){

this.heater=heater;

}

...

}

Dagger 可以直接注入成員變量郁妈。在這個(gè)例子中浑玛, 它獲取Heater對(duì)象, 并注入到成員變量heater噩咪,同時(shí)獲取Pump對(duì)象并注入到成員變量pump顾彰。

class CoffeeMaker{

@Inject Heaterheater;

@Inject Pump pump;

...

}

當(dāng)類中含有@Inject注釋的成員變量, 卻沒(méi)有@Inject注釋的構(gòu)造函數(shù)時(shí)剧腻, Dagger將使用類的默認(rèn)構(gòu)造函數(shù)拘央。若類中缺少@Inject注釋, 該類是不能由Dagger創(chuàng)建的书在。

Dagger不支持函數(shù)注入灰伟。

譯者:

若是某些類不需要Inject任何對(duì)象, 而又希望由Dagger創(chuàng)建該類對(duì)象儒旬。 這時(shí)栏账, 應(yīng)該至少添加一個(gè)@Inject的默認(rèn)構(gòu)造函數(shù), 否則會(huì)報(bào)異常栈源。

實(shí)現(xiàn)依賴關(guān)系

(Satisfying Dependencies挡爵, 實(shí)在想不出合適的中文對(duì)應(yīng))

默認(rèn)情況下, Dagger 通過(guò)構(gòu)造相應(yīng)類型的對(duì)象來(lái)實(shí)現(xiàn)依賴關(guān)系甚垦。當(dāng)請(qǐng)求一個(gè)CoffeMaker對(duì)象時(shí)茶鹃, Dagger將調(diào)用new CoffeeMaker()構(gòu)造函數(shù), 并賦值給@Inject標(biāo)記的成員變量艰亮。

但是@Inject并不是在任何情況下都可以:

接口類型不能被構(gòu)造

第三方的類不能被注釋構(gòu)造闭翩。

可配置的對(duì)象必須被配置好

譯者:

第一條是說(shuō), interfaces的注入Dagger是不能直接構(gòu)造對(duì)象的迄埃。當(dāng)然這樣了疗韵, 給你接口,誰(shuí)也構(gòu)造不了對(duì)象侄非。

第二條是說(shuō)蕉汪,Third-party classes can't be annotated. Dagger只能構(gòu)造那些有@Inject注釋的類, 即便沒(méi)有@Inject 成員變量逞怨, 也要至少有一個(gè)@Inject的構(gòu)造函數(shù)者疤。第三方的類顯然不能加入@Inject注釋, 因此也不能被Dagger構(gòu)造.

第三條是 Configurable objects must be configured!, 不明白啥意思叠赦, 求大神指教宛渐。

對(duì)那些使用@Inject效率極低或者awkward的情況, 可以使用@Provides注釋函數(shù)來(lái)實(shí)現(xiàn)依賴關(guān)系。這些函數(shù)的返回類型定義其實(shí)現(xiàn)的依賴關(guān)系窥翩。

例如业岁, 當(dāng)需要一個(gè)Heater時(shí), Dagger將調(diào)用provideHeater()函數(shù)獲取寇蚊。

@Provides HeaterprovideHeater(){

return new ElectricHeater();

}

@Provides注釋的函數(shù)也可以有他們自己的依賴關(guān)系笔时。下面這個(gè)Provides函數(shù)依賴于一個(gè)Thermosiphon對(duì)象:

@Provides PumpprovidePump(Thermosiphon pump){

return pump;

}

所有的@Provides函數(shù)必須屬于一個(gè)Module。這些Module類使用@Module注釋仗岸。

@Module

class DripCoffeeModule{

@Provides HeaterprovideHeater(){

return new ElectricHeater();

}

@Provides PumpprovidePump(Thermosiphon pump){

return pump;

}

}

通常情況下允耿, 約定@Provides函數(shù)以provide作為前綴, @Module類以Module作為后綴扒怖。

構(gòu)建ObjectGraph(對(duì)象圖表)

@Inject 和 @Provides 注釋的類構(gòu)建了一個(gè)對(duì)象圖表较锡。這些對(duì)象與對(duì)象之間通過(guò)依賴關(guān)系相互關(guān)聯(lián)。通過(guò)函數(shù)ObjectGraph.create()獲取這個(gè)對(duì)象圖表, 這個(gè)函數(shù)可以接受一個(gè)或多個(gè)Module作為參數(shù):

ObjectGraphobjectGraph=ObjectGraph.create(newDripCoffeeModule());

我們需要引導(dǎo)注入來(lái)使用這個(gè)對(duì)象圖表盗痒。 對(duì)于命令行程序蚂蕴, 通常需要注入一個(gè)主程序類;對(duì)于Android程序俯邓,通常需要注入activity類骡楼。在這個(gè)coffer例子中, CoffeeApp被用于引導(dǎo)注入稽鞭。我們請(qǐng)求這個(gè)對(duì)象圖表構(gòu)建一個(gè)CoffeeApp的對(duì)象實(shí)例:

class CoffeeAppimplementsRunnable{

@Inject CoffeeMaker coffeeMaker;

@Override public void run(){

coffeeMaker.brew();

}

public static void main(String[]args){

ObjectGraph objectGraph=ObjectGraph.create(newDripCoffeeModule());

CoffeeApp coffeeApp=objectGraph.get(CoffeeApp.class);

...

}

}

這里唯一缺少的是:這個(gè)對(duì)象圖表并不知道CoffeeApp這個(gè)可注入類鸟整。我們需要在@Module注釋中顯式的聲明。

@Module(

injects=CoffeeApp.class

)

class DripCoffeeModule{

...

}

injects選項(xiàng)使得可以在編譯的過(guò)程中檢查對(duì)象圖表是有有效朦蕴, 從而更早的檢測(cè)問(wèn)題篮条,以加快開(kāi)發(fā)速度,降低重構(gòu)時(shí)的風(fēng)險(xiǎn)吩抓。

現(xiàn)在涉茧, 對(duì)象圖表已經(jīng)構(gòu)建好, 根對(duì)象也已被注入琴拧, 我們就可以運(yùn)行這個(gè)Coffee 程序了。

$ java -cp ... coffee.CoffeeApp

~ ~ ~ heating ~ ~ ~

=> => pumping => =>

[_]P coffee! [_]P

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末嘱支,一起剝皮案震驚了整個(gè)濱河市蚓胸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌除师,老刑警劉巖沛膳,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異汛聚,居然都是意外死亡锹安,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)叹哭,“玉大人忍宋,你說(shuō)我怎么就攤上這事》缯郑” “怎么了糠排?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)超升。 經(jīng)常有香客問(wèn)我入宦,道長(zhǎng),這世上最難降的妖魔是什么室琢? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任乾闰,我火速辦了婚禮,結(jié)果婚禮上盈滴,老公的妹妹穿的比我還像新娘涯肩。我一直安慰自己,他們只是感情好雹熬,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布宽菜。 她就那樣靜靜地躺著,像睡著了一般竿报。 火紅的嫁衣襯著肌膚如雪铅乡。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,155評(píng)論 1 299
  • 那天烈菌,我揣著相機(jī)與錄音阵幸,去河邊找鬼。 笑死芽世,一個(gè)胖子當(dāng)著我的面吹牛挚赊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播济瓢,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼荠割,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了旺矾?” 一聲冷哼從身側(cè)響起蔑鹦,我...
    開(kāi)封第一講書(shū)人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎箕宙,沒(méi)想到半個(gè)月后嚎朽,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡柬帕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年哟忍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了狡门。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡锅很,死狀恐怖其馏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情粗蔚,我是刑警寧澤尝偎,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站鹏控,受9級(jí)特大地震影響致扯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜当辐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一抖僵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧缘揪,春花似錦耍群、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至袖裕,卻和暖如春曹抬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背急鳄。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工谤民, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人疾宏。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓张足,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親坎藐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子为牍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353

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