Java:内省(Introspector)

  内省(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;
}
原文地址:https://www.cnblogs.com/wangmingshun/p/5398417.html