天天看点

Map与JavaBean互转原理(内省机制)

1.javabean 转 map

  • 定义一个Person的javabean
public class Person {

        private String name;
        private int age;

        public Person() {
            super();
        }

        public Person(String name,int age){
            this.name=name;
            this.age=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;
        }

        @Override
        public String toString() {
            return "Person [name=" + name + ", age=" + age + "]";
        }



    }
           

解说:

定义一个Person的javabean是用来下面演示demo使用
           
  • 将map集合转javabean
/**
         * javabean转成map
         * @param obj
         * @return
         * @throws Exception
         */
        public static Map<String,Object> bean2Map(Object obj) throws Exception{
            Map<String, Object> map =new HashMap<>();
            // 获取person类的BeanInfo对象
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            //获取属性描述器
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {

                //获取属性名
                String key = propertyDescriptor.getName();
                if(key.equals("class"))
                    continue;
                //获取该属性的值
                Method readMethod = propertyDescriptor.getReadMethod();
                通过反射来调用Person的定义的getName()方法
                Object value = readMethod.invoke(obj);
                map.put(key, value);
            }
            return map;
        }

        /**
         * 打印map集合
         * @param map
         */
        private static void printMap(Map<String, Object> map) {
            for (Entry<String, Object> m : map.entrySet()) {
                System.out.println(m.getKey()+"="+m.getValue());
            }
            System.out.println("---------------------------------");
        }

        -------------------------------
        执行main方法:
        public static void main(String[] args) throws Exception {
            Person per=new Person("liujun",);
            Map<String, Object> bean2Map = bean2Map(per);
            printMap(bean2Map);
        }

        ----------------------
        输出的结果:
        name=liujun
        age=
        ---------------------------------
           

解说:

1.Introspector 类:获取person类的BeanInfo对象

2.BeanInfo 类:person类的BeanInfo对象

3.PropertyDescriptor 类:person类的属性描述器

2.map 转 javabean

/**
     * map集合转javabean
     * @param map
     * @param clz
     * @return
     * @throws Exception
     */

    public static <T>T map2Bean(Map<String,Object> map , Class<T> clz) throws Exception{
        //new 出一个对象
        T obj=clz.newInstance();
        // 获取person类的BeanInfo对象
        BeanInfo beanInfo = Introspector.getBeanInfo(clz);
        //获取属性描述器
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
            //获取属性名
            String key = propertyDescriptor.getName();
            Object value=map.get(key);
            if(key.equals("class"))
                continue;
            Method writeMethod = propertyDescriptor.getWriteMethod();
            //通过反射来调用Person的定义的setName()方法
            writeMethod.invoke(obj,value);
        }
        return obj;
    }

    -------------------------------
    执行main方法:
    public static void main(String[] args) throws Exception {
        Person per=new Person("liujun",);
        Map<String, Object> bean2Map = bean2Map(per);
        printMap(bean2Map);
        Person map2Bean = map2Bean(bean2Map, Person.class);
        System.out.println(map2Bean.toString());
    }

    -----------------------------
    输出的结果:
    name=liujun
    age=
    ---------------------------------
    Person [name=liujun, age=]
           

3.转换的原理(内省机制)

  • 什么是内省机制?

    内省机制是获取JavaBean的成员(事件,方法,属性),设置/获取属性值

  • 内省机制与反射有什么区别?

    反射是获取类的字节码对象,通过字节码对象创建类的对象,调用相关方法

  • 内省机制的核心类:

    Introspector

    Introspector类为访问目标Jave Bean支持的属性、事件和方法提供了标准方法。对于属性、事件和方法中的每一类信息,Introspector会分别分析目标bean以及其父类,寻找显式或隐式信息并用其构建一个能够全面描述目标bean的BeanInfo对象。过调用Introspector.getBeanInfo()方法来获得指定类的bean信息
               
    BeanInfo
    BeanInfo类是为了获取对bean属性的控制权。只需提供属性名和所属的bean类,就可以为每个属性构建一个PropertyDescriptor
               
    PropertyDescriptor
    PropertyDescriptor是属性描述器,通过PropertyDescriptor可以获取javabean中的定义的属性、事件和方法。
               
  • 内省机制代码的分析:
public static void main(String[] args) throws Exception {
            //通过Introspector获取person类的BeanInfo对象
            BeanInfo beanInfo = Introspector.getBeanInfo(Person.class);
            //通过beanInfo对象获取属性描述器propertyDescriptors
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            //遍历每一个属性描述器PropertyDescriptors     
            for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
                System.out.println("-------------");
                //获取某个属性的名称:例如:Person的定义的name属性名
                System.out.println(propertyDescriptor.getName());
                //获取某个属性的类型:例如:Person的定义的name属性的类型是class java.lang.String
                System.out.println(propertyDescriptor.getPropertyType());
                //获取某个属性的getxxx()方法,例如:Person的定义的getName()方法
                Method readMethod = propertyDescriptor.getReadMethod();
                //获取某个属性的setxxx()方法,例如:Person的定义的setName()方法
                Method writeMethod = propertyDescriptor.getWriteMethod();
                System.out.println(readMethod);
                System.out.println(writeMethod);
            }
        }

        -------------------------------

        输出的结果:

        -------------
        age
        int
        public int xmg.day24.neisheng.Person.getAge()
        public void xmg.day24.neisheng.Person.setAge(int)
        -------------
        class
        class java.lang.Class
        public final native java.lang.Class java.lang.Object.getClass()
        null
        -------------
        name
        class java.lang.String
        public java.lang.String xmg.day24.neisheng.Person.getName()
        public void xmg.day24.neisheng.Person.setName(java.lang.String)