如果在 Class A 中,有 Class B 的實(shí)例,則稱 Class A 對(duì) Class B 有一個(gè)依賴。例如下面類 Human 中用到一個(gè) Father 對(duì)象,我們就說類 Human 對(duì)類 Father 有一個(gè)依賴。
public class Human { ... Father father; ... public Human() { father = new Father(); }}仔細(xì)看這段代碼我們會(huì)發(fā)現(xiàn)存在一些問題: (1). 如果現(xiàn)在要改變 father 生成方式,如需要用new Father(String name)初始化 father,需要修改 Human 代碼; (2). 如果想測(cè)試不同 Father 對(duì)象對(duì) Human 的影響很困難,因?yàn)?father 的初始化被寫死在了 Human 的構(gòu)造函數(shù)中; (3). 如果new Father()過程非常緩慢,單測(cè)時(shí)我們希望用已經(jīng)初始化好的 father 對(duì)象 Mock 掉這個(gè)過程也很困難。
上面將依賴在構(gòu)造函數(shù)中直接初始化是一種 Hard init 方式,弊端在于兩個(gè)類不夠獨(dú)立,不方便測(cè)試。我們還有另外一種 Init 方式,如下:
public class Human { ... Father father; ... public Human(Father father) { this.father = father; }}上面代碼中,我們將 father 對(duì)象作為構(gòu)造函數(shù)的一個(gè)參數(shù)傳入。在調(diào)用 Human 的構(gòu)造方法之前外部就已經(jīng)初始化好了 Father 對(duì)象。像這種非自己主動(dòng)初始化依賴,而通過外部來傳入依賴的方式,我們就稱為依賴注入。 現(xiàn)在我們發(fā)現(xiàn)上面 1 中存在的兩個(gè)問題都很好解決了,簡(jiǎn)單的說依賴注入主要有兩個(gè)好處: (1). 解耦,將依賴之間解耦。 (2). 因?yàn)橐呀?jīng)解耦,所以方便做單元測(cè)試,尤其是 Mock 測(cè)試。
依賴注入的實(shí)現(xiàn)有多種途徑,而在 Java 中,使用注解是最常用的。通過在字段的聲明前添加 @Inject 注解進(jìn)行標(biāo)記,來實(shí)現(xiàn)依賴對(duì)象的自動(dòng)注入。
public class Human { ... @Inject Father father; ... public Human() { }}上面這段代碼看起來很神奇:只是增加了一個(gè)注解,F(xiàn)ather 對(duì)象就能自動(dòng)注入了?這個(gè)注入過程是怎么完成的?
實(shí)質(zhì)上,如果你只是寫了一個(gè) @Inject 注解,F(xiàn)ather 并不會(huì)被自動(dòng)注入。你還需要使用一個(gè)依賴注入框架,并進(jìn)行簡(jiǎn)單的配置。現(xiàn)在 Java 語言中較流行的依賴注入框架有 Google Guice、SPRing 等,而在 Android 上比較流行的有 RoboGuice、Dagger 等。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注