Java 依賴注入的思考
什麼是依賴注入
這裡展開一下,控制反轉,依賴注入,是說把控制的主動權轉移了,不由呼叫者決定要調誰來實現,而是由被注入決定誰去實現
依賴注入到底有啥好處呢?
我使用過一些 依賴注入框架——但是他們的實現在我看來,就是在使用類似反射的機制!!
不讓物件 new 出來,就降低了依賴!
——難道,我寫一個簡單的 反射類,我就相當於寫出了一個 依賴注入框架嗎???
一個反射類可以實現的功能;為什麼 那些大型公司會用一個團隊來開發?
依賴注入的優勢
首先我們需要知道,人們在很長的一段時間裡都是利用控制反轉原則規定:應用程式的流程取決於在程式執行時物件圖的建立。通過抽象定義的物件互動可以實現這樣的動態流程。而使用依賴注入技術或者服務定位器便可以完成執行時繫結。
使用依賴注入可以帶來以下好處:
依賴的注入和配置獨立於元件之外。
因為物件是在一個獨立、不耦合的地方初始化,所以當注入抽象方法的時候,我們只需要修改物件的實現方法,而不用大改程式碼庫。
依賴可以注入到一個元件中:我們可以注入這些依賴的模擬實現,這樣使得測試更加簡單。
可以看到,能夠管理建立例項的範圍是一件非常棒的事情。按我的觀點,你app中的所有物件或者協作者都不應該知道有關例項建立和生命週期的任何事情,這些都應該由我們的依賴注入框架管理的。
利用面向物件的思想。打個比方
你需要錘子,你可以
1、自己去造。用java的話說就是呼叫者建立被呼叫者
2、你可以要找到生產錘子的工廠,向工廠購買即可。對應java的工廠模式。
3、你可以打電話找到賣錘子的商店,讓人把錘子送貨上門。對應spring的依賴注入
以上第1種辦法,要求被呼叫的Java類出現在呼叫者的程式碼裡。無法實現二者之間的鬆耦合
第2種辦法,呼叫者無須關心被呼叫者具體實現過程,只需要找到符合某種標準(介面)的例項,即可使用
第3種辦法,呼叫者無須自己定位工廠,程式執行到需要被呼叫者時,系統自動提供被呼叫者例項。呼叫者和被呼叫者通過spring管理。他們的關係由spring維護
反射最終還是需要new來實現一個例項化物件,而依賴注入真正解決了這個問題
Java中的依賴注入
依賴注入的確是個簡單的技術,但是spring這些框架的強大,遠不是因為它會依賴注入,反射中,最終不還是創建出了例項嗎?spring預設情況下獲取一個bean是單例的,而不是new出例項給你。而且正是有了這種介面式的注入設計,才會有這麼多開源技術可以通過spring簡單整合執行,節省了大量的整合工作
再來個例項,某個類要使用第三方實現來處理快遞流程,它注入了一個標準介面,裡面有查運費,查收貨地,查快遞配送狀態等標準方法。而實現類有多種,比如申通的實現,圓通的實現。
現在可以用spring進行配置了,喜歡用哪家的就注入哪家的,還可以注入個工廠類來同時使用多家的。反射怎麼搞?從申通的實現換到圓通實現時,把要反射的類名字全部改一遍嗎?
好吧好吧,跑偏了,其實博主是搞安卓開發的,這裡再引用安卓中的例子來解釋
android中的依賴注入
舉個大家最常見卻又經常忽略的例子吧
現在非常流行的MVP框架,他的很多思想非常不錯,比如把M層與V層分離,這是V層專注UI,邏輯控制由P層來控制。這是其相比MVC來說非常大的一個痛點。
但是,他也同時違背了很多java設計的原則。
比如開閉原則(V層大改時,P層也要修改)依賴倒置,介面隔離(形式上解耦,但職責分工角度耦合,V層與P層的聯絡)單一職責原則(V層直接持有P層的引用)。。。。
好吧,原諒我扯遠了,MVP部分的優化以及MVVM的一些對比後面再另寫一篇專門講。這裡我們來看看V層持有P層的引用,這個問題完全是可以有下面的主角(Dagger2)來實現解耦
依賴注入,可以把例項化的過程交給被呼叫者,把控制的主動權轉移了。
使用了Dagger2,不由V層來決定要調哪個P層,而是由被注入決定誰去實現,V層專心UI,測試時專心在P層進行。
大型框架具備 “依賴注入”,AOP(呼叫攔截,android中也支援),物件生命週期的控制,其他的物件控制