dubbo里面的JavaBeanDescriptor是怎么进行序列化和反序列化的?

序列化的操作就是:1 变成JavaBeanAccessor对象。 2 把value值塞进去 3通过IdentityHashMap(普通hashmap可以通过equals方法刷新掉,IdentityHashMap用内存地址作为key)对已经序列化好的描述符缓存起来复用

变成JavaBeanAccessor对象:

 if (cl.isEnum()) {
            return new JavaBeanDescriptor(cl.getName(), JavaBeanDescriptor.TYPE_ENUM);
        } else if (cl.isArray()) {
            return new JavaBeanDescriptor(cl.getComponentType().getName(), JavaBeanDescriptor.TYPE_ARRAY);
        } else if (ReflectUtils.isPrimitive(cl)) {
            return new JavaBeanDescriptor(cl.getName(), JavaBeanDescriptor.TYPE_PRIMITIVE);
        } else if (Class.class.equals(cl)) {
            return new JavaBeanDescriptor(Class.class.getName(), JavaBeanDescriptor.TYPE_CLASS);
        } else if (Collection.class.isAssignableFrom(cl)) {
            return new JavaBeanDescriptor(cl.getName(), JavaBeanDescriptor.TYPE_COLLECTION);
        } else if (Map.class.isAssignableFrom(cl)) {
            return new JavaBeanDescriptor(cl.getName(), JavaBeanDescriptor.TYPE_MAP);
        } else {
            return new JavaBeanDescriptor(cl.getName(), JavaBeanDescriptor.TYPE_BEAN);
        }

  

 

value值塞进去:

 

private static void serializeInternal(JavaBeanDescriptor descriptor, Object obj, JavaBeanAccessor accessor, IdentityHashMap<Object, JavaBeanDescriptor> cache) {
        if (obj == null || descriptor == null) {
            return;
        }

        if (obj.getClass().isEnum()) {
            descriptor.setEnumNameProperty(((Enum<?>) obj).name());
        } else if (ReflectUtils.isPrimitive(obj.getClass())) {
            descriptor.setPrimitiveProperty(obj);
        } else if (Class.class.equals(obj.getClass())) {
            descriptor.setClassNameProperty(((Class<?>) obj).getName());
        } else if (obj.getClass().isArray()) {
            int len = Array.getLength(obj);
            for (int i = 0; i < len; i++) {
                Object item = Array.get(obj, i);
                if (item == null) {
                    descriptor.setProperty(i, null);
                } else {
                    JavaBeanDescriptor itemDescriptor = createDescriptorIfAbsent(item, accessor, cache);
                    descriptor.setProperty(i, itemDescriptor);
                }
            }
        } else if (obj instanceof Collection) {
            Collection collection = (Collection) obj;
            int index = 0;
            for (Object item : collection) {
                if (item == null) {
                    descriptor.setProperty(index++, null);
                } else {
                    JavaBeanDescriptor itemDescriptor = createDescriptorIfAbsent(item, accessor, cache);
                    descriptor.setProperty(index++, itemDescriptor);
                }
            }
        } else if (obj instanceof Map) {
            Map map = (Map) obj;
            for (Object key : map.keySet()) {
                Object value = map.get(key);
                Object keyDescriptor = key == null ? null : createDescriptorIfAbsent(key, accessor, cache);
                Object valueDescriptor = value == null ? null : createDescriptorIfAbsent(value, accessor, cache);
                descriptor.setProperty(keyDescriptor, valueDescriptor);
            } // ~ end of loop map
        } else {
            if (JavaBeanAccessor.isAccessByMethod(accessor)) {
                Map<String, Method> methods = ReflectUtils.getBeanPropertyReadMethods(obj.getClass());
                for (Map.Entry<String, Method> entry : methods.entrySet()) {
                    try {
                        Object value = entry.getValue().invoke(obj);
                        if (value == null) {
                            continue;
                        }
                        JavaBeanDescriptor valueDescriptor = createDescriptorIfAbsent(value, accessor, cache);
                        descriptor.setProperty(entry.getKey(), valueDescriptor);
                    } catch (Exception e) {
                        throw new RuntimeException(e.getMessage(), e);
                    }
                } // ~ end of loop method map
            } // ~ end of if (JavaBeanAccessor.isAccessByMethod(accessor))

            if (JavaBeanAccessor.isAccessByField(accessor)) {
                Map<String, Field> fields = ReflectUtils.getBeanPropertyFields(obj.getClass());
                for (Map.Entry<String, Field> entry : fields.entrySet()) {
                    if (!descriptor.containsProperty(entry.getKey())) {
                        try {
                            Object value = entry.getValue().get(obj);
                            if (value == null) {
                                continue;
                            }
                            JavaBeanDescriptor valueDescriptor = createDescriptorIfAbsent(value, accessor, cache);
                            descriptor.setProperty(entry.getKey(), valueDescriptor);
                        } catch (Exception e) {
                            throw new RuntimeException(e.getMessage(), e);
                        }
                    }
                } // ~ end of loop field map
            } // ~ end of if (JavaBeanAccessor.isAccessByField(accessor))

        } // ~ end of else

    } // ~ end of method serializeInternal

  

1 如果是基本类型,那么直接标记成基本类型,然后把obj的具体value塞入property-map中就够了.另外对于基本类型对应的装箱类型

Number.class.isAssignableFrom(Float.class)通过这个方法也会返回true,因为这些装箱类型也是继承自number 。 
装箱类型也是按照基本类型直接序列化的,塞入具体数值的

 


2 如果是数组:

int[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9};
JavaBeanDescriptor descriptor = JavaBeanSerializeUtil.serialize(array, JavaBeanAccessor.METHOD);
  是把数组作为整体当做obj传入进去,记录数组里面item的类型,并且标记成数组类型,得到一个JavaBeanDescriptor以后,只是标记了类型,还要把每个item序列化以后塞入array这个descriptor的property-map里面,也就是descriptor.setProperty(i, itemDescriptor); i表示这个item的下标,itemDescriptor表示第i个item序列化后的JavaBeanAccessor对象

 

 

3 list和isArray是不一样的,前者属于collection范畴,不过map、list、Array处理的逻辑比较类似

 

4 如果是自定义class:
走到这篇博文的最后一个else分支,把class-name的str存到JavaBeanAccessor对象中。塞入数值的方式是:
为了拿到这个class所有fileds的所有value,首先获取所有fileds,并且放到map里面,这个需要考虑super-class、transient、static(这个不需要序列化)。
然后通过fileds.get(instance)的反射方式拿到这个对象这个field的数值,再对这个数值翻译成描述符,最后才能把这个描述符塞入这个property-map里面

posted @ 2018-12-09 20:36  notlate  阅读(735)  评论(0编辑  收藏  举报