• 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;
    }
  • 相关阅读:
    ACM学习历程—HDU4415 Assassin’s Creed(贪心)
    ACM学习历程—HDU4417 Super Mario(树状数组 && 离线)
    ACM学习历程—HDU5423 Rikka with Tree(搜索)
    ACM学习历程—HDU5422 Rikka with Graph(贪心)
    ACM学习历程—ZOJ3777 Problem Arrangement(递推 && 状压)
    ACM学习历程—ZOJ3785 What day is that day?(数论)
    ACM学习历程—HYSBZ 2818 Gcd(欧拉函数 || 莫比乌斯反演)
    ACM学习历程—HDU5407 CRB and Candies(数论)
    日志-logback
    使用特定功能代码
  • 原文地址:https://www.cnblogs.com/wangmingshun/p/5398417.html
Copyright © 2020-2023  润新知