淺析Spring的IoC和DI

pjmike_pj發表於2018-08-20

前言

以前學習 Spring 框架的控制反轉和依賴注入,一直很懵懂,對這兩者概念和它們之間的關係沒有一個清晰的認識,所以這篇文章詳細去探索這被人稱道的 IoC 和 DI

什麼是控制反轉

IoC的全稱是Inversion of Control,中文意思就是控制反轉,那到底什麼是控制反轉呢,首先讓我們看一個例子。

假設有一個服務類ServiceA,要做doService這項工作,其中它想呼叫服務類ServiceB中的方法,要依賴於ServiceB類的服務,最直接的方法是直接在類的建構函式中新建相應的依賴類,去主動獲取依賴的物件,就好比裝修家,要用傢俱,就直接去買傢俱回來。這些工作都是我們主動去做的

public class ServiceA {
    private ServiceB serviceB;

    public ServiceA() {
        serviceB = new ServiceB();
    }

    public void doService() {
        System.out.println("do something..");
        serviceB.doSomething();
    }

    public static void main(String[] args) {
        ServiceA serviceA = new ServiceA();
        serviceA.doService();
    }
}
複製程式碼

但是,如果我們每次用到什麼依賴物件都要主動去獲取,顯得有些麻煩。如果有人能夠在我們需要的時候將某個依賴物件送過來,那就爽了,而IoC這個概念就應運而生,將情況反轉了,IoC就是提供更加簡潔的方式,現在有什麼,讓別人送過來就可以了,變主動為被動,讓別人為你服務,讓被依賴的物件自動進來。

總結一下: 控制反轉(IoC)實際上是一種設計思想,讓別人為你服務,在Java開發中,IoC意味著將你設計好的物件交給容器控制,而不是傳統的在你物件內部構造直接控制,IoC容器直接控制物件,由容器來幫忙建立及注入依賴物件,不需要我們去主動控制了。

什麼是依賴注入

DI-Dependency Injection,即"依賴注入",就是將例項變數傳入到一個物件中去。還有一種說法就是,由容器動態的將某個依賴關係注入到元件中去,即應用程式需要Ioc容器來提供物件需要的外部資源。

控制反轉和依賴注入的關係

IoC和DI是什麼關係呢,一種說法是是同一個概念的不同角度描述,另一種說法是,依賴注入可以看做是控制反轉的一種實現方式,IoC是一種思想,DI是一種設計模式,實現IoC的模式。其實我更傾向於後者,雖然兩者概念上有相似之處,但是將DI看做一種是IoC的思想的實現方式更讓人容易理解。

關於IoC和DI更權威的解釋,應該是大師級別的Martin Fowler的那篇文章 :Inversion of Control Containers and the Dependency Injection pattern

依賴注入的三種方式

構造方法注入

構造方法注入,就是被注入物件可以通過在其構造方法中宣告依賴物件的引數列表,讓外部IoC容器知道它需要哪些依賴物件,例如上面的服務ServiceA的例子

public class ServiceA {
    private ServiceB serviceB;

    public ServiceA(ServiceB serviceB) {
        this.serviceB = serviceB;
    }
    ...
}
複製程式碼

setter方法注入

對於JavaBean物件來說,通常會通過setXXX()和getXXX()來訪問對應屬性,setXXX()就稱為setter方法,通過setter方法,可以更改相應的物件屬性。所以當前物件只要為其依賴物件所對應的屬性新增setter方法,就可以通過setter方法將相應的依賴物件設定到被注入物件中。還是以服務ServiceA為例。

public void setServiceB(ServiceB serviceB) {
        this.serviceB = serviceB;
    }
複製程式碼

setter方法相對寬鬆,可以在物件構造完成後再注入就必須實現某個介面,這個介面提供了一個方法,用來為其注入依賴物件

介面注入

對於介面注入來說,如果被注入物件想要Ioc容器為其注入依賴物件,就必須實現某個介面,這個介面提供了一個方法,用來為其注入依賴物件。但是從注入方式的使用來說,介面注入是現在不提倡的一種方式,基本處於"退役"狀態,因為它強制被注入物件實現不必要的介面。

小結

IoC 是一種可以幫助我們解耦各業務物件間依賴關係的物件繫結方式,理解Ioc和DI能夠更好地幫助我們使用Spring框架。

參考資料 & 鳴謝

相關文章