內省機制
Java中提供了一套API用來訪問某個屬性的getter/setter方法,這些API存放與包java.beans中,一般的做法是通過類Introspector的getBeanInfo方法來獲取摸個對象的BeanInfo信息,然後通過BeanInfo來獲取屬性的描述器(PropertyDescriptor),通過這個屬性描述器就可以獲取某個屬性對應的getter/setter方法,然後我們就可以通過反射機制來調用這些方法。
內省機制用於查看和操作JavaBean中的屬性:
1)獲取JavaBean中的每一個屬性名、屬性類型
2)通過getter方法獲取屬性值,通過setter方法給屬性設置值
Introspector相關API
Introspector類
Introspector類提供了一種標準的方式作爲工具獲取類的屬性、事件、方法。
static BeanInfo getBeanInfo(Class<?> beanClass)在Java Bean上進行內省,瞭解其所有屬性、公開的方法
和事件。
BeanInfo類
該類爲Java Bean提供有關其Bean的方法、屬性、事件等顯示信息
MethodDescription[] getMethodDescriptors() 獲得方法相關的描述器
EventSetDescriptors[] getEventSetDescriptors() 獲得事件相關的描述去
PropertyDescriptor[] getpropertyDescriptors() 獲得屬性相關的描述器
PropertyDescriptor類
Method getReadMethod() 獲取用於讀取屬性值的方法
Method getWriteMethod()獲取用於寫入屬性值的方法
MethodDescriptor類
Method getMethod() 獲得此MethodDescriptor封裝的方法
使用內省機制
創建一個User類,我們爲name屬性添加setter方法,爲age屬性添加getter方法。
public class User {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
}
我們使用上面的User類進行測試
//獲取JavaBean的描述對象
BeanInfo beanInfo = Introspector.getBeanInfo(User.class);
//獲取JavaBean中屬性的描述器
PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
System.out.println(pd.getName());
System.out.println(pd.getReadMethod());
System.out.println(pd.getWriteMethod());
System.out.println("====================");
}
程序的執行結果如下
age
introspector.User.getAge()
null
====================
class
public final native java.lang.Class java.lang.Object.getClass()
null
====================
name
null
introspector.User.setName(java.lang.String)
====================
我們可以看到,我們並沒有class屬性,可是它是哪來的?
我們知道,其父類Object含有getClass方法,這個class屬性就是來自其父類。
如果我們不需要這個class屬性,我們可以使用Introspector提供的getBeanInfo的重載方法將Object排除,從而獲取User及User父類的屬性,但是不包括Object類中的屬性
getBeanInfo(Class<?> cls, Class<?> stopClass)
使用內省機制實現BeanUtils
//Bean -> Map
public static Map<String, Object> bean2Map(Object object) throws Exception {
Map<String, Object> map = new HashMap<String, Object>();
BeanInfo beanInfo = Introspector.getBeanInfo(object.getClass(),Object.class);
PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
String key = pd.getName();
Object value = pd.getReadMethod().invoke(object);
map.put(key, value);
}
return map;
}
//Map -> Bean
public static <T> T map2Bean(Map<String, Object> map, Class<T> beanType) throws Exception {
Object object = beanType.newInstance();
BeanInfo beanInfo = Introspector.getBeanInfo(beanType,Object.class);
PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
Object value = map.get(pd.getName());
pd.getWriteMethod().invoke(object, value);
}
return (T) object;
}