1. 程式人生 > 其它 >IOC與AOP的理解

IOC與AOP的理解

IOC與AOP的理解

IOC

IOC控制反轉概述

控制反轉是一種設計思想,將原本在程式中手動建立物件的控制權,交由Spring框架來管理。

IOC的思想最核心的地方在於,資源不由使用資源的雙方管理,而由不使用資源的第三方管理。這可以帶來很多好處:

  • 資源集中管理,實現資源的可配置和易管理
  • 降低了使用資源雙方的耦合度

理解依賴倒置原則

依賴倒置原則是設計模式的六大原則之一。其核心思想是面向介面程式設計,其定義如下:

  • 高層模組不應該依賴低層模組,兩者都應該依賴其抽象
  • 抽象不應該依賴細節
  • 細節應該依賴抽象

這一原則在Java語言中的表現:

  • 模組間的依賴通過抽象發生,實現類之間不發生直接的依賴關係,其依賴關係通過介面或抽象類產生
  • 介面或抽象類不依賴於實現類
  • 實現類依賴介面或抽象類

通過一個簡單的例子理解依賴倒置原則。

高層 —— 司機

package com.youzikeji.dr;

/**
 * 司機
 * 司機只會開賓士車
 */
public class Driver {
    public void drive (Benz benz) {
        benz.run();
    }
}

低層 —— 汽車

package com.youzikeji.dr;

/**
 * 賓士車
 */
public class Benz {
    public void run (){
        System.out.println("Benz車跑起了");
    }
}

高低層緊耦合

package com.youzikeji.dr;

/**
 * 司機和車緊耦合,系統可維護性大大降低
 */
public class Client {
    public static void main(String[] args) {
        Benz benz = new Benz();
        Driver driver = new Driver();
        driver.drive(benz);
    }
}

依賴倒置——面向介面程式設計

介面回撥:指的是可以把實現某一介面的類建立的物件的引用賦值給該介面宣告的介面變數,那麼該介面變數就可以呼叫被類實現的介面方法(當介面變數在呼叫被類實現的介面方法時,就是在通知相應的物件呼叫這個方法)。

package com.youzikeji.dr;

// 司機介面
public interface IDriver {
    // 抽象方法 —— 開車
    public void drive(ICar Car);
}
------------------------------------
package com.youzikeji.dr;

// 車的介面
public interface ICar {
    // 抽象方法 —— 車子運轉
    public void run();
}
------------------------------------
package com.youzikeji.dr;

public class MyDriver implements IDriver{
    @Override
    public void drive(ICar car) {
        car.run();
    }
}
------------------------------------
package com.youzikeji.dr;

public class MyBenz implements ICar{
    @Override
    public void run() {
        System.out.println("Benz車跑起來了");
    }
}
------------------------------------
package com.youzikeji.dr;

public class MyBmw implements ICar{
    @Override
    public void run() {
        System.out.println("bmw車跑起來了");
    }
}
------------------------------------
package com.youzikeji.dr;

/**
 * 依賴倒置後再測試
 */
public class DrClient {
    public static void main(String[] args) {
        IDriver driver = new MyDriver();
        ICar bmw = new MyBmw();

        driver.drive(bmw);

    }
}

使用依賴倒置的好處

  • 減少類間的耦合性,提高系統的穩定性,實現了團隊協作、並行開發
  • 提高程式碼的可讀性和可維護性

依賴傳遞(注入)的三種方式

所謂依賴注入就是把底層類作為引數傳入上層類,實現上層類對下層類的“控制

  • 建構函式傳遞

    package com.youzikeji.dr;
    
    // 司機介面
    public interface IDriver {
        // 抽象方法 —— 開車
        public void drive();
    }
    ------------------------------------
    package com.youzikeji.dr;
    
    public class MyDriver implements IDriver{
        private ICar car;
        // 建構函式注入
        public MyDriver(ICar _car) {
            this.car = _car;
        }
        public void drive() {
            this.car.run();
        }
    }
    
  • Setter方法傳遞

    package com.youzikeji.dr;
    
    // 司機介面
    public interface IDriver {
        // 設定車輛型號
        public void setCar(ICar car);
        // 抽象方法 —— 開車
        public void drive();
    }
    ------------------------------------
    package com.youzikeji.dr;
    
    public class MyDriver implements IDriver{
        private ICar car;
        // setter方式注入
        public void setCar(ICar car) {
            this.car = car;
        }
        public void drive() {
            this.car.run();
        }
    }
    
  • 介面宣告依賴物件 —— 上一節的方式

IOC Container

IOC 容器是 Spring 用來實現IOC 的載體,實際上就是個Map(key,value),Map 中存放的是各種物件。

因為採用了依賴注入,IOC容器在進行上層類的初始化時,不可避免地會大量地new物件,IOC容器可以自動對程式碼進行初始化,程式設計師只需要維護一個Configuration(可以是xml可以是一段程式碼),而不用每次初始化例項物件都要去寫大段的初始化程式碼。

IOC容器在建立一個例項物件時,先從最上層開始往下找依賴關係,到最底層後再一步一步new物件

以建造汽車為例,汽車需要車的骨架,車的骨架需要底盤,底盤需要輪胎。在建立汽車例項時,IOC容器需要進行如下操作:

  • 根據xml檔案或者configuration類,查物件之間的依賴,根據依賴關係,找到最底層的物件,然後往上進行建立。

IOC容器可以直接隱藏具體的建立例項的細節,在我們來看它就像一個工廠,當我們需要建立一個物件的時候,只需要配置好配置檔案/註解即可,完全不用考慮物件是如何被創建出來的。

圖源-知乎回答 by Mingqi

參考書籍:《設計模式之禪》 秦小波

AOP

AOP概述

Aspect-Oriented Programming,面向切面程式設計。能夠將那些與業務無關,卻為業務模組所共同呼叫的邏輯或責任(例如事務處理、日誌管理、許可權控制等)封裝起來,便於減少系統的重複程式碼降低模組間的耦合度,並有利於未來的可拓展性和可維護性。

Spring AOP的實現方式

Spring AOP的實現方式根據要代理的物件有沒有實現介面的情況進行選擇:

  • 要代理的物件實現了某個介面 —— 使用JDK Proxy
  • 對於沒有實現介面的物件 —— 無法使用JDK Proxy,使用Cglib生成一個被代理物件的子類來作為代理

兩種動態代理的簡單闡述——掘金社群

使用AOP的好處

使用AOP可以把一些通用功能抽象出來,在需要用到的地方直接使用即可,這樣大大簡化了程式碼量。我們需要增加新功能時也方便,這樣也提高了系統擴充套件性。日誌功能、事務管理等場景都用到了AOP。

利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發效率。

Spring AOP 參考及圖源——JavaGuide