内省(Introspector) 是Java 语言对 JavaBean 类属性、事件的一种缺省处理方法。
JavaBean是一种特殊的类,主要用于传递数据信息,这种类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。如果在两个模块之间传递信 息,可以将信息封装进JavaBean中,这种对象称为“值对象”(Value Object),或“VO”。方法比较少。这些信息储存在类的私有变量中,通过set()、get()获得。
例如UserInfo
public class UserInfo { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } publicint getAge() { return age; } publicvoid setAge(int age) { this.age = age; } }
在UserInfo中有属性name,我们可以通过getName,setName来访问其值或者设置其值.通过getName/setName来访问其属性name,这就是默认规则,java jdk中提供一套api用来访问某个属性的getter(),setter()方法即为内省。
JDK内省类库:
PropertyDescriptor类:
表示JavaBean类通过存储器导出一个属性。
主要方法:
1. getPropertyType(),获得属性的Class对象;
2. getReadMethod(),获得用于读取属性值的方法;getWriteMethod(),获得用于写入属性值的方法;
3. hashCode(),获取对象的哈希值;
4. setReadMethod(Method readMethod),设置用于读取属性值的方法;
5. setWriteMethod(Method writeMethod),设置用于写入属性值的方法。
import java.beans.PropertyDescriptor; import java.lang.reflect.Method; public class BeanInfoUtil { public static void main(String[] args) { UserInfo user = new UserInfo(); try { setProperty(user, "name"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(user.getName()); System.out.println(getProperty(UserInfo.class, "name")); } public static void setProperty(Object bean, String propertyName) throws Exception { PropertyDescriptor pd = new PropertyDescriptor(propertyName, bean.getClass()); Method methodSetProperty = pd.getWriteMethod(); methodSetProperty.invoke(bean, "123"); } public static String getProperty(Class<?> bean, String propertyName) { try { //通过反射实例化对象 Object be = bean.newInstance(); //创建PropertyDescriptor对象 PropertyDescriptor pd = new PropertyDescriptor(propertyName, be.getClass()); //调用getWriteMethod方法来为对象属性设置值 pd.getWriteMethod().invoke(be, "123"); //调用getReadMethod方法来获取对象的属性值 return (String) pd.getReadMethod().invoke(be, new Object[0]); } catch (Exception e) { e.printStackTrace(); } return null; } } class UserInfo { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
Introspector类:
将JavaBean中的属性封装起来进行操作。在程序把一个类当做JavaBean来看,就是调用Introspector.getBeanInfo()方法,得到的BeanInfo对象封装了把这个类当做JavaBean看的结果信息,即属性的信息。
getPropertyDescriptors(),获得属性的描述,可以采用遍历BeanInfo的方法,来查找、设置类的属性。具体代码如下:
public static void setPropertyIntrospector(Class<?> bean, String propertyName) { try { //第一个参数要分析的bean类, //第二个参数是从第一个参数开始到某个父类结束(当bean存在多个父类的时候可以通过该方法来限定) BeanInfo beanInfo = Introspector.getBeanInfo(bean, Object.class); //获取整个bean的属性描述 PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors(); if(pds != null && pds.length > 0) { for(PropertyDescriptor pd : pds) { if(pd.getName().equals(propertyName)) { Object obj = bean.newInstance(); pd.getWriteMethod().invoke(obj, "张三"); System.out.println(pd.getReadMethod().invoke(obj, new Object[0])); } } } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }}
======================使用内省机制完成javaBean和Map之间的相互转换====================
public static Map<String, Object> beanToMap(Object bean) { if(bean == null) return null; try { Map map = newHashMap(); BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass(), Object.class); PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors(); if(pds != null && pds.length > 0) { for(PropertyDescriptor pd : pds) { String key = pd.getName(); //过滤掉class属性 if(!key.equals("class")) { Object value = pd.getReadMethod().invoke(bean, new Object[]{}); //此处如果明确知道该类中含有某个对象可以这种处理 if(value instanceof Person) { //递归调用 Map m = beanToMap(value); map.put(key, m); } else { map.put(key, value); } } } } return map; } catch (Exception e) { e.printStackTrace(); } return null; } public static Object mapToBean(Class<?> beanClass, Map map) { if(map == null) return null; try { //内部实例化对象 Object bean = beanClass.newInstance(); BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass(), Object.class); PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors(); if(pds != null && pds.length > 0) { for(PropertyDescriptor pd : pds) { String key = pd.getName(); Object value = map.get(key); if(value instanceof Map) { //递归调用,嵌套map的转换,map中存放map,map中的map表示一个对象 Object obj = mapToBean(Person.class, (Map)value); pd.getWriteMethod().invoke(bean, obj); } else { pd.getWriteMethod().invoke(bean, value); } } } return bean; } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; }