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簡稱DI)
java中註解(Annotation)
依賴注入:就是目標類(目標類需要進行依賴初始化的類,下面都會用目標類一詞來指代)中所依賴的其他的類的初始化過程,不是通過手動編碼的方式創建,而是通過技術手段可以把其他的類的已經初始化好的實例自動注入到目標類中。
1

以下的內容我會嘗試着去模仿dagger2的作者是怎樣一步步完成dagger2這樣偉大的依賴注入類庫的場景來講解。


Inject

先看一段代碼:

class A{
B b = new B(…);
C c = new C();
D d = new D(new E());
F f = new F(…..);
}
上面的代碼完全沒任何問題,但是總感覺創建對象的這些代碼基本都是重複的體力勞動,那何嘗不想個辦法,把這些重複的體力勞動用一種自動化的、更省力的方法解決掉,這樣就可以讓開發的效率提高,可以把精力集中在重要的業務上了。
2
我們可以用註解(Annotation)來標註目標類中所依賴的其他類,同樣用註解來標註所依賴的其他類的構造函數,那註解的名字就叫Inject
3
這樣我們就可以讓目標類中所依賴的其他類與其他類的構造函數之間有了一種無形的聯繫。但是要想使它們之間產生直接的關係,還得需要一個橋樑來把它們之間連接起來。那這個橋樑就是Component了。
4


Component

Component也是一個註解類,一個類要想是Component,必須用Component註解來標註該類,並且該類是接口或抽象類。我們不討論具體類的代碼,我想從抽象概念的角度來討論Component。上文中提到Component在目標類中所依賴的其他類與其他類的構造函數之間可以起到一個橋樑的作用。
那我們看看這橋樑是怎麼工作的:
Component需要引用到目標類的實例,Component會查找目標類中用Inject註解標註的屬性,查找到相應的屬性後會接着查找該屬性對應的用Inject標註的構造函數(這時候就發生聯繫了),剩下的工作就是初始化該屬性的實例並把實例進行賦值。因此我們也可以給Component叫另外一個名字注入器(Injector)
5
小結下
目標類想要初始化自己依賴的其他類:
用Inject註解標註目標類中其他類
用Inject註解標註其他類的構造函數
若其他類還依賴於其他的類,則重複進行上面2個步驟
調用Component(注入器)的injectXXX(Object)方法開始注入(injectXXX方法名字是官方推薦的名字,以inject開始)
Component現在是一個注入器,就像注射器一樣,Component會把目標類依賴的實例注入到目標類中,來初始化目標類中的依賴。


Module

現在有個新問題:項目中使用到了第三方的類庫,第三方類庫又不能修改,所以根本不可能把Inject註解加入這些類中,這時我們的Inject就失效了。

那我們可以封裝第三方的類庫,封裝的代碼怎麼管理呢,總不能讓這些封裝的代碼散落在項目中的任何地方,總得有個好的管理機制,那Module就可以擔當此任。
可以把封裝第三方類庫的代碼放入Module中,像下面的例子:
6
注意:Module其實是一個簡單工廠模式,Module裏面的方法基本都是創建類實例的方法。接下來問題來了,因爲Component是注入器(Injector),我們怎麼能讓Component與Module有聯繫呢?

Component的新職責

Component是注入器,它一端連接目標類,另一端連接目標類依賴實例,它把目標類依賴實例注入到目標類中。上文中的Module是一個提供類實例的類,所以Module應該是屬於Component的實例端的(連接各種目標類依賴實例的端),Component的新職責就是管理好Module,Component中的modules屬性可以把Module加入Component,modules可以加入多個Module。
7

那接下來的問題是怎麼把Module中的各種創建類的實例方法與目標類中的用Inject註解標註的依賴產生關聯,那Provides註解就該登場了。


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來標註
8

本文爲轉載文章,原文地址請請點擊:Android:dagger2讓你愛不釋手-基礎依賴注入框架篇