内省机制
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;
}