1. 程式人生 > >Java內省機制的神奇行為舉止一例

Java內省機制的神奇行為舉止一例

【相關類庫】org.apache.commons.beanutils.BeanUtils,其中底層使用到了Java的內省方法。
【內省的一般應用形式】通過類Introspector 來獲取某個物件的 BeanInfo 資訊,然後通過 BeanInfo 來獲取屬性的描述器(PropertyDescriptor),通過這個屬性描述器就可以獲取某個屬性對應的 getter/setter方法,然後我們就可以通過反射機制來呼叫這些方法。
【程式碼使用】Introspector.getBeanInfo(Class<?> beanClass);拿BeanInfo物件。
【例子】例如一個price屬性,

1、定義 private Long price; // 價格
2、set方法

public void setPrice(Long price) {

this.price = price;

}
3、get方法

public String getPrice() {

return null == price ? null : StringUtil.priceToStr(price);

}
則通過內省只會拿到get方法。

【原理和注意事項】getBeanInfo()方法(返回GenericBeanInfo),其中有getTargetPropertyInfo(),會通過getPublicDeclaredMethods(beanClass);找出所有的get、set方法以PropertyDescriptor儲存在list(通常長度為2),然後通過hashmap(屬性名,list)暫存;
然後通過processPropertyDescriptors()進行篩選和合並,
(這個方法官方註釋 Populates the property descriptor table by merging the lists of Property descriptors.)
其中會判斷get方法的返回值和set方法的引數型別是否assignable,若不一致則以get方法為準,認為只有get方法符合要求。
然後儲存在Introspector的properties當中,供GenericBeanInfo的構造方法呼叫。
之後BeanInfo對外暴露getPropertyDescriptors(),取其中的properties。


注:java.beans.GenericBeanInfo當中,Introspector是public的,GenericBeanInfo反而是包級可見。
(官方註釋Package-private dup constructor * This must isolate the new object from any changes to the old object.)

【最佳實踐】
模型向檢視物件vo轉換時,vo屬性設定為傳給前端的型別,保持set、get方法型別一致,通過org.apache.commons.beanutils.BeanUtils轉換器進行轉換,而不要設定不同型別的get、set方法。