Spring IoC 究竟是什麼

前言

上一篇文章」咱們對 Spring 有了初步的認識,而 Spring 全家桶中幾乎全部組件都是依賴於 IoC 的。java

剛開始聽到 IoC,會以爲特別高大上,但其實掰開了很簡單。git

跟着個人腳步,一文帶你吃透 IoC 原理。程序員

本文主要講原理,圍繞「是何」、「爲什麼」來談,下一篇文章會講實踐部分,也就是「如何」。github

文本已收錄至個人 Github: https://github.com/xiaoqi6666/NYCSDEspring

是何

上一篇文章有同窗問我在官網該看哪些內容,怎麼找的,那今天的截圖裏都會有連接。框架

初識 IoC

根據上一篇文章咱們說的,Spring 全家桶中最重要的幾個項目都是基於 Spring Framework 的,因此咱們就以 Spring Framework 爲例來看文檔ide

首先它的右側有 Github 的連接,另外點到「LEARN」這裏,就會看到各個版本的文檔。學習

那咱們點「Reference Doc」,就可以看到它的一些模塊的介紹:this

(等下... 模塊?什麼是模塊?這個問題下文回答。)spa

第一章 Overview,講述它的歷史、設計原理等等;

第二章 Core,包含了 IoC 容器,AOP 等等,那天然是講 Spring 的核心了,要點進去好好看了。

點進去以後發現了寶貴的學習資料,一切的 what, why, how 均可以在這裏找到答案。

這裏很好的解釋了大名鼎鼎的 IoC - Inversion of Control, 控制反轉。

每次讀都會有新的體會和收穫。

我粗略的總結一下:控制反轉就是把建立和管理 bean 的過程轉移給了第三方。而這個第三方,就是 Spring IoC Container,對於 IoC 來講,最重要的就是容器

容器負責建立、配置和管理 bean,也就是它管理着 bean 的生命,控制着 bean 的依賴注入。

通俗點講,由於項目中每次建立對象是很麻煩的,因此咱們使用 Spring IoC 容器來管理這些對象,須要的時候你就直接用,不用管它是怎麼來的、何時要銷燬,只管用就行了。

舉個例子,就好像父母沒時間管孩子,就把小朋友交給託管所,就安心的去上班而不用管孩子了。
託兒所,就是第三方容器,負責管理小朋友的吃喝玩樂;
父母,至關於程序員,只管接送孩子,不用管他們吃喝。

等下,bean 又是什麼?

Bean 其實就是包裝了的 Object,不管是控制反轉仍是依賴注入,它們的主語都是 object,而 bean 就是由第三方包裝好了的 object。(想一下別人送禮物給你的時候都是要包裝一下的,本身造的就免了。

IoC 容器

既然說容器是 IoC 最重要的部分,那麼 Spring 如何設計容器的呢?
仍是回到官網,第二段有介紹哦:

答:使用 ApplicationContext,它是 BeanFactory 的子類,更好的補充並實現了 BeanFactory 的。

BeanFactory 簡單粗暴,能夠理解爲 HashMap:

  • Key - bean name
  • Value - bean object

但它通常只有 get, put 兩個功能,因此稱之爲「低級容器」。

ApplicationContext 多了不少功能,由於它繼承了多個接口,可稱之爲「高級容器」。在下文的搭建項目中,咱們會使用它。

ApplicationContext 的裏面有兩個具體的實現子類,用來讀取配置配件的:

  • ClassPathXmlApplicationContext - 從 class path 中加載配置文件,更經常使用一些;
  • FileSystemXmlApplicationContext - 從本地文件中加載配置文件,不是很經常使用,若是再到 Linux 環境中,還要改路徑,不是很方便。

當咱們點開 ClassPathXmlApplicationContext 時,發現它並非直接繼承 ApplicationContext 的,它有不少層的依賴關係,每層的子類都是對父類的補充實現。

而再往上找,發現最上層的 class 回到了 BeanFactory,因此它很是重要。

要注意,Spring 中還有個 FactoryBean,二者並無特別的關係,只是名字比較接近,因此不要弄混了順序。

爲了好理解 IoC,咱們先來回顧一下不用 IoC 時寫代碼的過程。

深刻理解 IoC

這裏用經典 class Rectangle 來舉例:

  • 兩個變量:長和寬
  • 自動生成 set() 方法和 toString() 方法

注意 ⚠️:必定要生成 set() 方法,由於 Spring IoC 就是經過這個 set() 方法注入的;
toString() 方法是爲了咱們方便打印查看。

public class Rectangle {
    private int width;
    private int length;

    public Rectangle() {
        System.out.println("Hello World!");
    }


    public void setWidth(int widTth) {
        this.width = widTth;
    }

    public void setLength(int length) {
        this.length = length;
    }

    @Override
    public String toString() {
        return "Rectangle{" +
                "width=" + width +
                ", length=" + length +
                '}';
    }
}

而後在 test 文件中手動用 set() 方法給變量賦值。

嗯,其實這個就是「解藕」的過程!

public class MyTest {
  @Test
  public void myTest() {
    Rectangle rect = new Rectangle();
    rect.setLength(2);
    rect.setWidth(3);
    System.out.println(rect);
  }
}

其實這就是 IoC 給屬性賦值的實現方法,咱們把「建立對象的過程」轉移給了 set() 方法,而不是靠本身去 new,就不是本身建立的了。

這裏我所說的「本身建立」,指的是直接在對象內部來 new,是程序主動建立對象的正向的過程;
這裏使用 set() 方法,是別人(test)給個人;
而 IoC 是用它的容器來建立、管理這些對象的,其實也是用的這個 set() 方法,不信,你把這個這個方法去掉或者改個名字試試?

幾個關鍵問題:

何爲控制,控制的是什麼?

答:是 bean 的建立、管理的權利,控制 bean 的整個生命週期。

何爲反轉,反轉了什麼?

答:把這個權利交給了 Spring 容器,而不是本身去控制,就是反轉。
由以前的本身主動建立對象,變成如今被動接收別人給咱們的對象的過程,這就是反轉。

舉個生活中的例子,主動投資和被動投資。

本身炒股、選股票的人就是主動投資,主動權掌握在本身的手中;
而買基金的人就是被動投資,把主動權交給了基金經理,除非你把這個基金賣了,不然具體選哪些投資產品都是基金經理決定的。

依賴注入

回到文檔中,第二句話它說:IoC is also known as DI.

咱們來談談 dependency injection - 依賴注入。

何爲依賴,依賴什麼?

程序運行須要依賴外部的資源,提供程序內對象的所須要的數據、資源。

何爲注入,注入什麼?

配置文件把資源從外部注入到內部,容器加載了外部的文件、對象、數據,而後把這些資源注入給程序內的對象,維護了程序內外對象之間的依賴關係。

因此說,控制反轉是經過依賴注入實現的。
可是你品,你細品,它們是有差異的,像是「從不一樣角度描述的同一件事」

  • IoC 是設計思想,DI 是具體的實現方式;
  • IoC 是理論,DI 是實踐;

從而實現對象之間的解藕。

固然,IoC 也能夠經過其餘的方式來實現,而 DI 只是 Spring 的選擇。

IoC 和 DI 也並不是 Spring 框架提出來的,Spring 只是應用了這個設計思想和理念到本身的框架裏去。

爲什麼

那麼爲何要用 IoC 這種思想呢?換句話說,IoC 能給咱們帶來什麼好處?

答:解藕。

它把對象之間的依賴關係轉成用配置文件來管理,由 Spring IoC Container 來管理。

在項目中,底層的實現都是由不少個對象組成的,對象之間彼此合做實現項目的業務邏輯。可是,不少不少對象緊密結合在一塊兒,一旦有一方出問題了,必然會對其餘對象有所影響,因此纔有瞭解藕的這種設計思想。

如上圖所示,原本 ABCD 是互相關聯在一塊兒的,當加入第三方容器的管理以後,每一個對象都和第三方法的 IoC 容器關聯,彼此之間再也不直接聯繫在一塊兒了,沒有了耦合關係,所有對象都交由容器來控制,下降了這些對象的親密度,就叫「解藕」。

那麼咱們下一篇文章就來說一下如何搭建一個 Spring 項目。

若是你喜歡這篇文章,記得給我點贊留言哦~大家的支持和承認,就是我創做的最大動力,咱們下篇文章見!

我是小齊,紐約程序媛,終生學習者,天天晚上 9 點,雲自習室裏不見不散!

更多幹貨文章見個人 Github: https://github.com/xiaoqi6666/NYCSDE

相關文章
相關標籤/搜索