dagger2 讓你愛不釋手:基礎依賴注入框架篇
前言
dagger2的大名我想大家都已經很熟了,它是解決Android或java中依賴注入的一個類庫(DI類庫)。當我看到一些開源的專案在使用dagger2時,我也有種匆匆欲動的感覺,因此就立馬想一探它的究竟,到底能給我帶來怎樣的好處。在學習使用dagger2的過程中,我遇到了以下的一些困惑:
- dagger2中的Inject,Component,Module,Provides等等都是什麼東東,有什麼作用?
- dagger2到底能帶來哪些好處?
- 怎樣把dagger2應用到具體專案中?
在具體學習dagger2的時候,看了好多部落格,看的時候感覺挺簡單的,但是在真正使用到專案中時候,腦袋就懵了,無從下手,Component應該怎麼用,能放些什麼方法? Module應該放些啥內容?Scope怎麼起到作用域控制?…..各種疑問就橫空而出。所以也許會有正在學習或即將要使用dagger2的同學在使用過程中遇到和我一樣的困惑
我會分幾節給講解dagger2。
本節內容
Inject,Component,Module,Provides它們是什麼?怎麼去理解它們?各自有什麼作用?主要從抽象的概念講解,不會涉及到具體程式碼的剖析。
提前科普知識點
在講解之前,我希望大家對以下知識點有所瞭解(知道的同學可以跳過)
- 依賴注入(Dependency Injection簡稱ID)
- java中註解(Annotation)
依賴注入:就是目標類(目標類需要進行依賴初始化的類,下面都會用目標類一詞來指代)中所依賴的其他的類的初始化過程,不是通過手動編碼的方式建立,而是通過技術手段
若您還是對依賴注入不瞭解,點選我可以讓您瞭解更多
dagger2就是實現依賴注入的一種技術手段。
其次java註解的概念用法我們就不講了,dagger2中核心點就是java註解,點選我可以瞭解更多java註解知識
正式開始
以下的內容我會嘗試著去模仿dagger2的作者是怎樣一步步完成dagger2這樣偉大的依賴注入類庫的場景來講解(首先這個場景是我意淫的,大家勿噴,模仿該場景主要目的是為了能由簡到難一步步更深入的瞭解dagger2)
Inject是什麼鬼
先看一段程式碼:
123456 | classA{Bb=newB(...);Cc=newC();Dd=newD(newE());Ff=newF(.....);} |
上面的程式碼完全沒任何問題,但是總感覺建立物件的這些程式碼基本都是重複的體力勞動,那何嘗不想個辦法,把這些重複的體力勞動用一種自動化的、更省力的方法解決掉,這樣就可以讓開發的效率提高,可以把精力集中在重要的業務上了。
我們可以用註解(Annotation)來標註目標類中所依賴的其他類,同樣用註解來標註所依賴的其他類的建構函式,那註解的名字就叫Inject
12345678910 | classA{@InjectBb;}classB{@InjectB(){}} |
這樣我們就可以讓目標類中所依賴的其他類與其他類的建構函式之間有了一種無形的聯絡。但是要想使它們之間產生直接的關係,還得需要一個橋樑來把它們之間連線起來。那這個橋樑就是Component了。
Inject.pngComponent又是什麼鬼
Component也是一個註解類,一個類要想是Component,必須用Component註解來標註該類,並且該類是介面或抽象類。我們不討論具體類的程式碼,我想從抽象概念的角度來討論Component。上文中提到Component在目標類中所依賴的其他類與其他類的建構函式之間可以起到一個橋樑的作用。
那我們看看這橋樑是怎麼工作的:
component.pngComponent需要引用到目標類的例項,Component會查詢目標類中用Inject註解標註的屬性,查詢到相應的屬性後會接著查詢該屬性對應的用Inject標註的建構函式(這時候就發生聯絡了),剩下的工作就是初始化該屬性的例項並把例項進行賦值。因此我們也可以給Component叫另外一個名字注入器(Injector)
小結下
目標類想要初始化自己依賴的其他類:
- 用Inject註解標註目標類中其他類
- 用Inject註解標註其他類的建構函式
- 若其他類還依賴於其他的類,則重複進行上面2個步驟
- 呼叫Component(注入器)的injectXXX(Object)方法開始注入(injectXXX方法名字是官方推薦的名字,以inject開始)
Component現在是一個注入器,就像注射器一樣,Component會把目標類依賴的例項注入到目標類中,來初始化目標類中的依賴。
為啥又造出個Module
現在有個新問題:專案中使用到了第三方的類庫,第三方類庫又不能修改,所以根本不可能把Inject註解加入這些類中,這時我們的Inject就失效了。
那我們可以封裝第三方的類庫,封裝的程式碼怎麼管理呢,總不能讓這些封裝的程式碼散落在專案中的任何地方,總得有個好的管理機制,那Module就可以擔當此任。
可以把封裝第三方類庫的程式碼放入Module中,像下面的例子:
1234567 | @ModulepublicclassModuleClass{//A是第三方類庫中的一個類AprovideA(){returnA();}} |
,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來標註
dagger2中Scope(作用域),Qualifier(限定符),Singleton(單例),SubComponent等都是對dagger2中整個注入依賴注入框架進行的補充,我們後面會繼續講解,敬請期待……
希望能幫您更好的理解dagger2。
歡迎各位多多交流,轉載請標明出處。
打賞支援我寫出更多好文章,謝謝!
打賞作者
打賞支援我寫出更多好文章,謝謝!
任選一種支付方式