dagger2——依賴注入框架篇(上)

前言

使用Dagger2前你必須了解的一些設計原則
Dagger2 最清晰的使用教程
請先看以上兩篇文章

dagger2 的大名我想大家都已經很熟了,它是解決Android或java中依賴注入的一個類庫(DI類庫)。當我看到一些開源的項目在使用dagger2時,我也有種匆匆欲動的感覺,因此就立馬想一探它的究竟,到底能給我帶來怎樣的好處。在學習使用dagger2的過程中,我遇到了以下的一些困惑:

  • dagger2中的Inject,Component,Module,Provides等等都是什么東東,有什么作用?
  • dagger2到底能帶來哪些好處?
  • 怎樣把dagger2應用到具體項目中?

在具體學習dagger2的時候,看了好多博客,看的時候感覺挺簡單的,但是在真正使用到項目中時候,腦袋就懵了,無從下手,Component應該怎么用,能放些什么方法? Module應該放些啥內容?Scope怎么起到作用域控制?.....各種疑問就橫空而出。所以也許會有正在學習或即將要使用dagger2的同學在使用過程中遇到和我一樣的困惑,因此我決定把我對dagger2的理解、使用經驗分享給大家,希望能對大家有幫助。我會分幾節給講解dagger2。
本節內容
Inject,Component,Module,Provides 它們是什么?怎么去理解它們?各自有什么作用?主要從抽象的概念講解,不會涉及到具體代碼的剖析。
提前科普知識點
在講解之前,我希望大家對以下知識點有所了解(知道的同學可以跳過)
依賴注入設計模式
依賴注入(Dependency Injection簡稱DI)
java中注解(Annotation)

依賴注入:就是目標類(目標類需要進行依賴初始化的類,下面都會用目標類一詞來指代)中所依賴的其他的類的初始化過程,不是通過手動編碼的方式創建,而是通過技術手段可以把其他的類的已經初始化好的實例自動注入到目標類中。

di.png

若您還是對依賴注入不了解,點擊我可以讓您了解更多dagger2就是實現依賴注入的一種技術手段
其次java注解的概念用法我們就不講了,dagger2中核心點就是java注解,點擊我可以了解更多java注解知識

正式開始

以下的內容我會嘗試著去模仿dagger2的作者是怎樣一步步完成dagger2這樣偉大的依賴注入類庫的場景來講解(首先這個場景是我意淫的,大家勿噴,模仿該場景主要目的是為了能由簡到難一步步更深入的了解dagger2)
Inject是什么鬼
先看一段代碼:

class A{
    B b = new B();
    C c = new C();
    D d = new D(new E());
    F f = new F(.....);
}

上面的代碼完全沒任何問題,但是總感覺創建對象的這些代碼基本都是重復的體力勞動,那何嘗不想個辦法,把這些重復的體力勞動用一種自動化的、更省力的方法解決掉,這樣就可以讓開發的效率提高,可以把精力集中在重要的業務上了。
我們可以用注解(Annotation)來標注目標類中所依賴的其他類,同樣用注解來標注所依賴的其他類的構造函數,那注解的名字就叫Inject
class A{ @Inject B b; } class B{ @Inject B(){ } }

這樣我們就可以讓目標類中所依賴的其他類與其他類的構造函數之間有了一種無形的聯系。但是要想使它們之間產生直接的關系,還得需要一個橋梁來把它們之間連接起來。那這個橋梁就是Component了。


Inject.png

Component又是什么鬼

Component也是一個注解類,一個類要想是Component,必須用Component注解來標注該類,并且該類是接口或抽象類。我們不討論具體類的代碼,我想從抽象概念的角度來討論Component。上文中提到Component在目標類中所依賴的其他類與其他類的構造函數之間可以起到一個橋梁的作用。
那我們看看這橋梁是怎么工作的:Component需要引用到目標類的實例,Component會查找目標類中用Inject注解標注的屬性,查找到相應的屬性后會接著查找該屬性對應的用Inject標注的構造函數(這時候就發生聯系了),剩下的工作就是初始化該屬性的實例并把實例進行賦值。因此我們也可以給Component叫另外一個名字注入器(Injector)

component.png

小結下目標類想要初始化自己依賴的其他類:
用Inject注解標注目標類中其他類
用Inject注解標注其他類的構造函數
若其他類還依賴于其他的類,則重復進行上面2個步驟
調用Component(注入器)的injectXXX(Object)方法開始注入(injectXXX方法名字是官方推薦的名字,以inject開始)

Component現在是一個注入器,就像注射器一樣,Component會把目標類依賴的實例注入到目標類中,來初始化目標類中的依賴。
為啥又造出個Module
現在有個新問題:項目中使用到了第三方的類庫,第三方類庫又不能修改,所以根本不可能把Inject注解加入這些類中,這時我們的Inject就失效了。
那我們可以封裝第三方的類庫,封裝的代碼怎么管理呢,總不能讓這些封裝的代碼散落在項目中的任何地方,總得有個好的管理機制,那Module就可以擔當此任。可以把封裝第三方類庫的代碼放入Module中,像下面的例子:

@Module public class ModuleClass{
        //A是第三方類庫中的一個類
        A provideA(){
           return A();
        }
}

Module 其實是一個簡單工廠模式,Module里面的方法基本都是創建類實例的方法。接下來問題來了,因為Component是注入器(Injector),我們怎么能讓Component與Module有聯系呢?
Component的新職責
Component是注入器,它一端連接目標類,另一端連接目標類依賴實例,它把目標類依賴實例注入到目標類中。上文中的Module是一個提供類實例的類,所以Module應該是屬于Component的實例端的(連接各種目標類依賴實例的端),Component的新職責就是管理好Module,Component中的modules屬性可以把Module加入Component,modules可以加入多個Module。

Component_橋梁概念.png

那接下來的問題是怎么把Module中的各種創建類的實例方法與目標類中的用Inject注解標注的依賴產生關聯,那Provides注解就該登場了。
Provides最終解決第三方類庫依賴注入問題
Module中的創建類實例方法用Provides進行標注,Component在搜索到目標類中用Inject注解標注的屬性后,Component就會去Module中去查找用Provides標注的對應的創建類實例方法,這樣就可以解決第三方類庫用dagger2實現依賴注入了。

總結

Inject,Component,Module,Provides是dagger2中的最基礎最核心的知識點。奠定了dagger2的整個依賴注入框架
Inject主要是用來標注目標類的依賴和依賴的構造函數
Component它是一個橋梁,一端是目標類,另一端是目標類所依賴類的實例,它也是注入器(Injector)負責把目標類所依賴類的實例注入到目標類中,同時它也管理Module。
Module和Provides是為解決第三方類庫而生的,Module是一個簡單工廠模式,Module可以包含創建類實例的方法,這些方法用Provides來標注

component_module_inject.png

希望能幫您更好的理解dagger2。
dagger2——重點概念講解,融合篇(中)
原文地址

參考文章,更詳細

[Android]使用Dagger 2依賴注入 - DI介紹(翻譯)

[Android]使用Dagger 2依賴注入 - API(翻譯)

[Android]使用Dagger 2依賴注入 - 自定義Scope(翻譯)

[Android]使用Dagger 2依賴注入 - 圖表創建的性能(翻譯)

[Android]Dagger2Metrics - 測量DI圖表初始化的性能(翻譯)

[Android]使用Dagger 2進行依賴注入 - Producers(翻譯)

[Android]在Dagger 2中使用RxJava來進行異步注入(翻譯):

[Android]使用Dagger 2來構建UserScope(翻譯):

[Android]在Dagger 2中Activities和Subcomponents的多綁定(翻譯)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,572評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,071評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,409評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,569評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,360評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,895評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,979評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,123評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,643評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,559評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,742評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,250評論 5 356
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,981評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,363評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,622評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,354評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,707評論 2 370

推薦閱讀更多精彩內容

  • Dagger2 入門 2016-12-21 更新:添加@Subcomponent注解以及Lazy與Provider...
    fxzou閱讀 28,566評論 77 331
  • 幾個問題 看到Dagger2這個詞的時候,相信很多人會有很多的疑問如下:Dagger2如何使用在例子中?Injec...
    codeHoward閱讀 7,039評論 4 10
  • 部分內容參考自:[Android]使用Dagger 2依賴注入 - DI介紹(翻譯)[Android]使用Dagg...
    AItsuki閱讀 47,697評論 66 356
  • (一) 不知何時開始,夾道的梧桐葉紛紛變成了鎏金色。也許是秋日的第一縷涼風,拂得它們一心歡喜,臉色也都熱情了不少。...
    BitE咬咬閱讀 668評論 0 0
  • 8.6 今天上午我們有一起聚集在大廳,玩瘋狂超市的游戲。簡單的來說就是要過關斬將開公司,想方設法去融資!謝謝我是不...
    故事雨閱讀 333評論 0 0