本文以「父親需要兒子/女兒協助完成任務」為場景,分別用 C# 原生反射與 Java 模擬 Spring 實現 IoC 容器。
IPerson 介面(被調用者契約)Son、Daughter 實作 IPersonFather(調用者)持有 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...
Person(name 屬性)、Persons(持有 son、daughter 兩個 Person 參考)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 模擬 Spring | Spring 實際實現 |
|---|---|---|---|
| 配置方式 | 程式碼硬編碼類別名稱 | 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 覆蓋等疑難雜症。