面對多種業務變體(如不同消息類型的處理邏輯),傳統做法在客戶端直接 new ConcreteClass() 導致:
解決路徑:定義統一接口 + 外部配置映射 + 反射動態實例化。
Operatorpublic interface Operator {
// 統一入口,參數靈活擴展
java.util.List act(String content, String content2, java.util.List params);
}
public class Success implements Operator {
public java.util.List act(String c1, String c2, java.util.List p) {
List r = new ArrayList();
r.add(c1); r.add(c2); r.add(p); return r;
}
}
public class Load implements Operator { /* 同結構,業務邏輯不同 */ }
// 可無限擴展:Store、Verify、Notify 等
emp.properties:消息頭 → 類名映射# 成功響應
1000=Success
# 普通文本消息下發
2000=Load
# 客戶上行消息存儲
3000=Store
TestReflect:核心邏輯封裝public class TestReflect {
// 1. 讀取配置,獲取類名
private String loadProtocol(String header) { ... }
// 2. 獲取上下文類加載器(支援 Web 容器、OSGi 等環境)
private static ClassLoader getTCL() { ... }
// 3. 統一響應入口
public String response(String header, String c1, String c2, List list) {
String className = "org.bromon.reflect." + loadProtocol(header).trim();
Class> clazz = Class.forName(className); // 動態加載
Operator op = (Operator) clazz.newInstance(); // 實例化
// 反射獲取方法並調用(參數類型精確匹配)
Class>[] paramTypes = {String.class, String.class, List.class};
Method method = clazz.getMethod("act", paramTypes);
Object[] args = {c1, c2, list};
List result = (List) method.invoke(op, args); // 執行業務邏輯
return (String) result.get(0);
}
}
TestReflect tr = new TestReflect();
List list = new ArrayList(); list.add("測試List");
tr.response("2000", "Load1", "Load2", list);
// 輸出: result2==[Load1, Load2, [測試List]]
tr.response("1000", "Success1", "Success2", list);
// 輸出: result2==[Success1, Success2, [測試List]]
| 維度 | 傳統硬編碼 | 反射+配置驅動 |
|---|---|---|
| 新增業務類型 | 修改客戶端代碼、重新編譯部署 | 僅需添加類文件 + 更新配置,零代碼變更 |
| 部署靈活性 | 整體重啟 | 支持熱部署、插件化擴展 |
| 測試隔離 | 難以 Mock 具體實現 | 可注入測試專用實現類 |
| 異常處理 | 編譯期發現 | 需加強運行時異常捕獲(ClassNotFound、NoSuchMethod、IllegalAccess 等) |
ConcurrentHashMap 緩存。@Autowired + @Qualifier、Google Guice 可替代手工反射,提供生命週期管理、AOP 攔截等企業級能力。Java 反射機制賦予了「運行時決定類型」的動態能力,配合接口隔離與外部配置,能構建高內聚、低耦合、極易擴展的插件化架構。雖反射帶來性能與類型安全代價,但通過緩存、框架封裝、模塊化演進,已成為企業級應用實現開閉原則的基石技術之一。