Spring系列第二講 控制反轉(IoC)與依賴注入(DI),晦澀難懂麼?

qwer1030274531發表於2020-10-27

引出spring

有2個類,A和B,如下:

public class A{
    public void m1(){}}public class B{
    public void m1();}1234567

上面2個類都有同樣的m1方法。

現在我們呼叫B的m1方法完成一些事情,而B中的m1方法需要呼叫A中的m1方法才可以完成這個事情,所以B的程式碼變成了下面這樣:

public class B{
    private A a; // @1
    public B(){
        this.a = new A(); //@2
    }
    public void m1(){
        this.a.m1(); //@3
    }}12345678910111213

分析一下上面程式碼:

@1:B類中宣告瞭一個A型別的屬性a

@2:new了一個A物件,賦給了a屬性

@3:B類中的m1方法中去呼叫a.m1()完成業務操作

先說一下什麼是依賴關係?

當a物件完成某些操作需要呼叫b物件中的方法來實現時,說明a依賴於物件b,a和b是依賴關係。

上面程式碼中B的m1需要呼叫A的m1方法,說明了B依賴於A

上面程式碼存在一些問題問題

B類中a物件的建立被寫死在B的構造方法中了,如果我們想在建立不同的B物件的時候,使用不同的a物件,此時是無能為力的;程式碼也不利於測試,由於B中a的建立被寫死在構造方法中了,我們想測試一下B中不同a物件的效果,此時只能去修改B中的構造方法。

上面程式碼需要最佳化,B中a物件的建立不能寫死,可以讓外部傳入進去,調整一下變成了下面這樣:

public class B{
    private A a;
    public B(A a){
        this.a = a;
    }
    public void m1(){
        this.a.m1(); 
    }}123456789101112

上面程式碼可以在建立B物件的時候,將外部建立好的a物件傳入進去,此時a的控制權交給了使用者,建立B物件如下:

A a = new A();B b = new B(a);b.m1();123

上面程式碼我們再擴充套件一下,如果B類中還需要依賴很多類似於A的物件,比如需要依賴於C、D、E、F或者更多物件,首先是需要調整B的構造方法,修改老的構造方法不是很好,可以在B中新增一些構造方法。

但是使用B的時候就變成了下面這樣:

A a = new A();C c = new C();D d = new D();E e = new E();F f = new F();...B b = new B(a,c,d,e,f,...);b.m1();12345678

使用者建立B物件之前,需要先將B依賴的物件都給建立好,然後B依賴的這些物件傳遞給B物件,如果有很多地方都需要用到B型別的物件,都採用這種new的寫法,程式碼量比較大,也不方便維護,如果B中新增了依賴,又需採用new的方式先建立好被依賴的物件,然後將被依賴的物件填充給B物件。

上面建立物件之前,需要先將被依賴物件透過new的方式建立好,然後將其傳遞給B,這些工作都是B的使用者自己去做的,所有物件的建立都是由使用者自己去控制的,弊端上面也說了,程式碼量也比較大,程式碼耦合度比較高(依賴有調整,改動也比較大),也不利於擴充套件。

那麼有沒有更好的方式來解決這些問題呢?

上面B物件以及B依賴的物件都是使用者自己主動去控制其建立的,能不能找一個第三方來把這個事情給做了,比如給第三方一個清單,清單中告訴第三方我需要用到B物件以及B需要依賴的物件,然後由這個第三方去負責建立和組裝B物件,使用者需要使用B物件的時候,只需要向第三方發起一個查詢,如果第三方那邊有B物件,直接將其內部組裝好的B物件返回就可以了,整個系統中所有需要用到的物件都可以列個清單,讓第三方幫忙創造,用的時候只需要向第三方索取就可以了,當B中依賴的物件有新增或者刪除的時候,只需要去調整一下清單就可以了,這個事情spring已經幫我們實現了。

spring容器

spring容器的概念,容器這個名字起的相當好,容器可以放很多東西,我們的程式啟動的時候會建立spring容器,會給spring容器一個清單,清單中列出了需要建立的物件以及物件依賴關係,spring容器會建立和組裝好清單中的物件,然後將這些物件存放在spring容器中,當程式中需要使用的時候,可以到容器中查詢獲取,然後直接使用。

IOC:控制反轉

使用者之前使用B物件的時候都需要自己去建立和組裝,而現在這些建立和組裝都交給spring容器去給完成了,使用者只需要去spring容器中查詢需要使用的物件就可以了;這個過程中B物件的建立和組裝過程被反轉了,之前是使用者自己主動去控制的,現在交給spring容器去建立和組裝了,物件的構建過程被反轉了,所以叫做控制反轉;IOC是是面相物件程式設計中的一種設計原則,主要是為了降低系統程式碼的耦合度,讓系統利於維護和擴充套件。

DI:依賴注入

依賴注入是spring容器中建立物件時給其設定依賴物件的方式,比如給spring一個清單,清單中列出了需要建立B物件以及其他的一些物件(可能包含了B型別中需要依賴物件),此時spring在建立B物件的時候,會看B物件需要依賴於哪些物件,然後去查詢一下清單中有沒有包含這些被依賴的物件,如果有就去將其建立好,然後將其傳遞給B物件;可能B需要依賴於很多物件,B建立之前完全不需要知道其他物件是否存在或者其他物件在哪裡以及被他們是如何建立,而spring容器會將B依賴物件主動建立好並將其注入到B中去,比如spring容器建立B的時候,發現B需要依賴於A,那麼spring容器在清單中找到A的定義並將其建立好之後,注入到B物件中。

總結

IOC控制反轉,是一種設計理念,將物件建立和組裝的主動控制權利交給了spring容器去做,控制的動作被反轉了,降低了系統的耦合度,利於系統維護和擴充套件,主要就是指需要使用的物件的組裝控制權被反轉了,之前是自己要做的,現在交給spring容器做了。

DI依賴注入,表示spring容器中建立物件時給其設定依賴物件的方式,透過某些注入方式可以讓系統更靈活,比如自動注入等可以讓系統變的很靈活,這個後面的文章會細說。

spring容器:主要負責容器中物件的建立、組裝、物件查詢、物件生命週期的管理等等操作。

下一篇開始詳細講解spring的使用了

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30239065/viewspace-2730338/,如需轉載,請註明出處,否則將追究法律責任。

相關文章