天天看點

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)