首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

IOC 控制反轉深度剖析:從 C# 依賴倒置原則到 Java Spring 核心實現原理

     編輯:Java 相關知識

前言:概念釐清——依賴倒置 vs 依賴注入 vs 控制反轉

  • DIP(依賴倒置原則):架構層級原則——高層模組不依賴低層模組,雙方依賴抽象;抽象不依賴細節,細節依賴抽象。(C# 《大話設計模式》語境)
  • IoC(控制反轉):運行時特徵——物件 A 依賴 B,但 A 不建立 B,而是從外部容器取得 B。
  • DI(依賴注入):IoC 的具體實現手段——容器透過建構子/屬性/方法將依賴注入調用者。

本文以「父親需要兒子/女兒協助完成任務」為場景,分別用 C# 原生反射與 Java 模擬 Spring 實現 IoC 容器。

C# 實作:原生反射實現簡易容器

類別結構

  • IPerson 介面(被調用者契約)
  • Son、Daughter 實作 IPerson
  • Father(調用者)持有 IPerson,透過 Container 取得實例
  • Container 以 Activator.CreateInstance(Type.GetType(typeName)) 反射建立物件

// 介面
public interface IPerson { void Operation(); }

// 被調用者
public class Son : IPerson { public void Operation() => Console.WriteLine("son is the operator"); }
public class Daughter : IPerson { public void Operation() => Console.WriteLine("daughter is the operator"); }

// 容器
public class Container {
    public IPerson GetApplication(string typeName) {
        return (IPerson)Activator.CreateInstance(Type.GetType(typeName));
    }
}

// 調用者
public class Father {
    private readonly IPerson person;
    public Father(string typeName) {
        person = new Container().GetApplication(typeName);
    }
    public void Operation() => person.Operation();
}

// 測試
var fa = new Father("IOCBlog.Son"); fa.Operation(); // 輸出 son...
fa = new Father("IOCBlog.Daughter"); fa.Operation(); // 輸出 daughter...

Java 模擬 Spring:XML 配置 + SAX 解析 + 反射建立 Bean

核心組件

  1. JavaBean:Person(name 屬性)、Persons(持有 son、daughter 兩個 Person 參考)
  2. 配置檔 IocApplication.xml:定義 bean id、class、property(value/ref)
  3. BeanFactory:
      ① SAX 解析 XML → ② 反射實例化 Bean → ③ 依賴注入(setter/建構子) → ④ 存入 Map<String,Object> beanMap

關鍵代碼片段


// XML 片段

    mark


    


// BeanFactory 核心
public class BeanFactory {
    private Map<String,Object> beanMap = new HashMap<>();
    public void init(String xmlPath) {
        SAXReader reader = new SAXReader();
        reader.addHandler("/beans/bean", new BeanHandler(this)); // 處理  節點
        reader.read(new File(xmlPath));
    }
    public Object getBean(String id) { return beanMap.get(id); }
}

// BeanHandler 邏輯(簡化)
// 1. 讀取 id、class 屬性 → Class.forName(className).newInstance()
// 2. 遍歷  子節點:
//    - 若有  → 呼叫 setter 注入基本型別/字串
//    - 若有  → 從 beanMap 取得參考 → 呼叫 setter 注入物件參考
// 3. 將實例存入 beanMap[id] = instance

測試驗證


BeanFactory factory = new BeanFactory();
factory.init("src/IocApplication.xml");
Person son = (Person) factory.getBean("son");
System.out.println("Son's name: " + son.getName()); // 輸出 mark

核心差異與心法比較

維度C# 簡易容器Java 模擬 SpringSpring 實際實現
配置方式程式碼硬編碼類別名稱XML 外部化配置XML / Annotation / Java Config
生命週期管理無(每次新建)單例 Map 快取完整 Bean 生命週期(初始化/銷毀/後置處理器)
依賴解析建構子注入單一依賴Setter 注入多依賴建構子/Setter/欄位注入,循環依賴處理
AOP 整合無無動態代理(JDK/CGLIB)無縫織入

總結

IoC 本質是「好萊塢原則:Don't call us, we'll call you」。從 C# 手動反射到 Java XML 配置,再到 Spring 豐富的生態(@Autowired、@Component、條件裝配、Profile 等),核心思想始終未變:將物件建立與依賴管理權移交給容器,業務代碼專注於核心邏輯。理解底層反射與解析機制,能幫助排查 Spring 啟動失敗、循環依賴、Bean 覆蓋等疑難雜症。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved