也談Spring之依賴注入DI/控制反轉IOC

首先提問: 什麼是 Spring IOC 容器?

        Spring 框架的核心是 Spring 容器。容器創建對象,將它們裝配在一起,配置它們並管理它們的完整生命週期。Spring 容器使用依賴注入來管理組成應用程序的組件。容器通過讀取提供的配置元數據來接收對象進行實例化,配置和組裝的指令。該元數據可以通過 XML,Java 註解或 Java 代碼提供。

然而,依賴注入到底是什麼?

        依賴注入(Dependency Injection):兩個對象之間的依賴關係在程序運行時由外部容器動態的注入依賴行爲方式稱爲依賴注入簡稱DI。

        在依賴注入中,您僅需聲明,不必創建對象,但必須描述如何創建它們。您不是直接在代碼中將組件和服務連接在一起,而是描述配置文件中哪些組件需要哪些服務。由 IoC 容器將它們裝配在一起。

        控制反轉:是一種將組件依賴關係的創建和管理置於程序外部的技術。
        由容器控制程序之間的關係,而不是由代碼直接控制,由於控制權由代碼轉向了容器,所以稱爲反轉。
        對象與對象之間的關係可以簡單的理解爲對象之間的依賴關係,舉例:在類 A 的方法中需要調用類 B 的方法來完成功能,那麼首先在 A 類需要有類 B 的一個實例,叫做 A 類依賴於B 類。
        一個需要特定的依賴的組件一般會涉及一個依賴對象,在 IOC 的概念中叫做目標 (target) 。換句話說, IOC提供了這樣的服務,使一個組件能夠在它的整個生命週期中訪問它的依賴和服務,用這種方法與它的依賴進行交互。總的來說, IOC能夠被分解爲兩種子類型:依賴注入和依賴查找。

那麼,可以通過幾種方式完成依賴注入?

通常,依賴注入可以通過三種方式完成:

        1) 構造函數注入

        2) setter 注入

        3) 接口注入

        在 Spring Framework 中,僅使用構造函數和 setter 注入。

注入方式:區分構造函數注入和、setter 注入

構造函數注入 setter 注入
沒有部分注入 有部分注入
不會覆蓋 setter 屬性 會覆蓋 setter 屬性
任意修改都會創建一個新實例 任意修改不會創建一個新實例
適用於設置很多屬性 適用於設置少量屬性

接着,Spring 中有多少種 IOC 容器?

       1)BeanFactory - BeanFactory 就像一個包含 bean 集合的工廠類。它會在客戶端要求時實例化 bean。

       2)ApplicationContext - ApplicationContext 接口擴展了 BeanFactory 接口。它在 BeanFactory 基礎上提供了一些額外的功能。

區分 BeanFactory 和 ApplicationContext。

BeanFactory ApplicationContext
它使用懶加載 它使用即時加載
它使用語法顯式提供資源對象 它自己創建和管理資源對象
不支持國際化 支持國際化
不支持基於依賴的註解 支持基於依賴的註解

再然後,IoC 可以帶來哪些好處?

IoC 的一些好處是:

        1)減少代碼量。

        2)它將使應用程序易於測試,因爲它不需要單元測試用例中的任何單例或 JNDI 查找機制。

       3)它以最小的影響和最少的侵入機制促進鬆耦合。

       4)它支持即時的實例化和延遲加載服務。

最後,給出Spring IoC 的實現機制。

Spring 中的 IoC 的實現原理就是工廠模式加反射機制。

示例:

package com.spring;

/**
 * Created by Liuxd on 2018-11-11.
 */
interface Animal {
    public abstract void speak();
}

class Cat implements Animal {
    public void speak() {
        System.out.println("I am a cat");
    }
}

class Dog implements Animal {
    public void speak() {
        System.out.println("I am a dog");
    }
}

class BeanFactory {
    public static Animal getInstance(String ClassName) {
        Animal f = null;
        try {
            f = (Animal) Class.forName(ClassName).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return f;
    }
}

public class Client {
    public static void main(String[] a) {
        Animal animal = BeanFactory.getInstance("com.spring.Cat");
        if (null != animal) {
            animal.speak();
        }
        Animal animal2 = BeanFactory.getInstance("com.spring.Dog");
        if (null != animal2) {
            animal2.speak();
        }
    }
}

打印結果:

I am a cat
I amd a dog

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章