# 前言
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
若您還是對**依賴注入**不了解,[點擊我可以讓您了解更多](http://baike.baidu.com/link?url=QB0xjWcya3HWr4p9VwZ6hxjcO-fybEbuLv6nBvHDbg99-HyLzstlGayZfIu4Swrw8QSyTmUdz3EVPRaOLdrGGyEXoasaIQra3wfojaX1RJgZ6Nl8mazfQrJYuwXA1G5TT9CM3cLqVdhLk-lG0Bo6SWo4wT-yaTv62_7GuOo-VcaGwpnohMlG0GIcnizbKVJQ)
dagger2就是實現**依賴注入**的一種**技術手段**。
其次java注解的概念用法我們就不講了,dagger2中核心點就是java注解,[點擊我可以了解更多java注解知識](http://baike.baidu.com/link?url=aTMlLy_LOV3j6d9aszLbSOwUajGSL_CI1LagJ8bh--PxtOmrCI5vSwewTPCxLcVe07Q4BNoxqFX3TpsJ5B9yPq)
## 正式開始
以下的內容我會嘗試著去模仿**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。
[Android:dagger2讓你愛不釋手-重點概念講解、融合篇](http://www.jianshu.com/p/1d42d2e6f4a5)
**個人簡介**
本人是一名android開發工程師,開發android多年,若有志同道合的朋友想聯系我,可以加我的:qq/微信: 704451290
作者:牛曉偉
鏈接:http://www.jianshu.com/p/cd2c1c9f68d4
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
- 0-發現
- AndroidInterview-Q-A
- Android能讓你少走彎路的干貨整理
- LearningNotes
- temp
- temp11
- 部分地址
- 0-待辦任務
- 待補充列表
- 0-未分類
- AndroidView事件分發與滑動沖突處理
- Spannable
- 事件分發機制詳解
- 1-Java
- 1-Java-01基礎
- 未歸檔
- 你應該知道的JDK知識
- 集合框架
- 1-Java-04合集
- Java之旅0
- Java之旅
- JAVA之旅01
- JAVA之旅02
- JAVA之旅03
- JAVA之旅04
- JAVA之旅05
- JAVA之旅06
- JAVA之旅07
- JAVA之旅08
- JAVA之旅09
- java之旅1
- JAVA之旅10
- JAVA之旅11
- JAVA之旅12
- JAVA之旅13
- JAVA之旅14
- JAVA之旅15
- JAVA之旅16
- JAVA之旅17
- JAVA之旅18
- JAVA之旅19
- java之旅2
- JAVA之旅20
- JAVA之旅21
- JAVA之旅22
- JAVA之旅23
- JAVA之旅24
- JAVA之旅25
- JAVA之旅26
- JAVA之旅27
- JAVA之旅28
- JAVA之旅29
- java之旅3
- JAVA之旅30
- JAVA之旅31
- JAVA之旅32
- JAVA之旅33
- JAVA之旅34
- JAVA之旅35
- 1-Java-05辨析
- HashMapArrayMap
- Java8新特性
- Java8接口默認方法
- 圖解HashMap(1)
- 圖解HashMap(2)
- 2-Android
- 2-Android-1-基礎
- View繪制流程
- 事件分發
- AndroidView的事件分發機制和滑動沖突解決
- 自定義View基礎
- 1-安卓自定義View基礎-坐標系
- 2-安卓自定義View基礎-角度弧度
- 3-安卓自定義View基礎-顏色
- 自定義View進階
- 1-安卓自定義View進階-分類和流程
- 10-安卓自定義View進階-Matrix詳解
- 11-安卓自定義View進階-MatrixCamera
- 12-安卓自定義View進階-事件分發機制原理
- 13-安卓自定義View進階-事件分發機制詳解
- 14-安卓自定義View進階-MotionEvent詳解
- 15-安卓自定義View進階-特殊形狀控件事件處理方案
- 16-安卓自定義View進階-多點觸控詳解
- 17-安卓自定義View進階-手勢檢測GestureDetector
- 2-安卓自定義View進階-繪制基本圖形
- 3-安卓自定義View進階-畫布操作
- 4-安卓自定義View進階-圖片文字
- 5-安卓自定義View進階-Path基本操作
- 6-安卓自定義View進階-貝塞爾曲線
- 7-安卓自定義View進階-Path完結篇偽
- 8-安卓自定義View進階-Path玩出花樣PathMeasure
- 9-安卓自定義View進階-Matrix原理
- 通用類介紹
- Application
- 2-Android-2-使用
- 2-Android-02控件
- ViewGroup
- ConstraintLayout
- CoordinatorLayout
- 2-Android-03三方使用
- Dagger2
- Dagger2圖文完全教程
- Dagger2最清晰的使用教程
- Dagger2讓你愛不釋手-終結篇
- Dagger2讓你愛不釋手-重點概念講解、融合篇
- dagger2讓你愛不釋手:基礎依賴注入框架篇
- 閱讀筆記
- Glide
- Google推薦的圖片加載庫Glide:最新版使用指南(含新特性)
- rxjava
- 這可能是最好的RxJava2.x入門教程完結版
- 這可能是最好的RxJava2.x入門教程(一)
- 這可能是最好的RxJava2.x入門教程(三)
- 這可能是最好的RxJava2.x入門教程(二)
- 這可能是最好的RxJava2.x入門教程(五)
- 這可能是最好的RxJava2.x入門教程(四)
- 2-Android-3-優化
- 優化概況
- 各種優化
- Android端秒開優化
- apk大小優化
- 內存分析
- 混淆
- 2-Android-4-工具
- adb命令
- 一鍵分析Android的BugReport
- 版本控制
- git
- git章節簡述
- 2-Android-5-源碼
- HandlerThread 源碼分析
- IntentService的使用和源碼分析
- 2-Android-9-辨析
- LRU算法
- 什么是Bitmap
- 常見圖片壓縮方式
- 3-Kotlin
- Kotlin使用筆記1-草稿
- Kotlin使用筆記2
- kotlin特性草稿
- Kotlin草稿-Delegation
- Kotlin草稿-Field
- Kotlin草稿-object
- 4-JavaScript
- 5-Python
- 6-Other
- Git
- Gradle
- Android中ProGuard配置和總結
- gradle使用筆記
- Nexus私服搭建
- 編譯提速最佳實踐
- 7-設計模式與架構
- 組件化
- 組件化探索(OKR)
- 1-參考列表
- 2-1-組件化概述
- 2-2-gradle配置
- 2-3-代碼編寫
- 2-4-常見問題
- 2-9-值得一讀
- 8-數據結構與算法
- 0臨時文件
- 漢諾塔
- 8-數據-1數據結構
- HashMap
- HashMap、Hashtable、HashSet 和 ConcurrentHashMap 的比較
- 遲到一年HashMap解讀
- 8-數據-2算法
- 1個就夠了
- Java常用排序算法(必須掌握的8大排序算法)
- 常用排序算法總結(性能+代碼)
- 必須知道的八大種排序算法(java實現)
- 9-職業
- 閱讀
- 書單
- 面試
- 面試-01-java
- Java面試題全集駱昊(上)
- Java面試題全集駱昊(下)
- Java面試題全集駱昊(中)
- 面試-02-android
- 40道Android面試題
- 面試-03-開源源碼
- Android圖片加載框架最全解析(二),從源碼的角度理解Glide的執行流程
- 面試-07-設計模式
- 面試-08-算法
- 面試-09-其他
- SUMMARY
- 版權說明
- temp111