企業級應用常面臨資料欄位頻變的挑戰:傳統 Java Bean 在編譯期固定屬性,導致每次增減欄位都需修改原始碼、重新編譯部署。本文系統梳理「標準屬性 → 擴展屬性 → 動態 Bean」三階演進,並以 Apache Commons BeanUtils 為核心,示範如何在運行期動態定義、存取屬性,解決「以動制動」的彈性需求。
| 類型 | 特徵 | 關鍵介面/類 |
|---|---|---|
| 簡單屬性 | 單一值或陣列,無外部依賴 | 標準 getter/setter 命名慣例 |
| 相關屬性 | 屬性變更發送 PropertyChangeEvent 通知監聽器 | PropertyChangeListener, PropertyChangeSupport |
| 約束屬性 | 監聽器可拋 PropertyVetoException 否決變更 | VetoableChangeListener, VetoableChangeSupport |
缺點:屬性在編譯期靜態綁定,無法應對動態資料模型。
Commons BeanUtils PropertyUtils 定義五種存取格式,透過反射在運行期解析:
bean.propbean.prop1.prop2.prop3bean.list[0]、bean.array[2]bean.map(key)bean.prop1.list[2].map(key)關鍵優勢:將 List/Map 內部元素視為獨立屬性,不再把整個集合當作單一屬性,實現無限擴充。
DynaProperty[] props = {
new DynaProperty("firstName", String.class),
new DynaProperty("lastName", String.class)
};
DynaClass dynaClass = new BasicDynaClass("Employee", null, props);
DynaBean emp = dynaClass.newInstance();
PropertyUtils.setProperty(emp, "firstName", "John");
Struts form-beans.xml 風格:
<form-bean name="logonForm" type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="username" type="java.lang.String"/>
<form-property name="password" type="java.lang.String"/>
</form-bean>
搭配 RequestUtils.applicationClass() 將字串轉 Class,實現「靜態型別檢查 + 動態屬性定義」的平衡。


DynaBean + Map 後端儲存。DynaClass,實現真正的「配置即代碼」。BasicDynaClass 為不可變,DynaBean 實例需自行同步。