• 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里面

  • 相关阅读:
    grid与oracle用户下oracle程序权限不一致导致无法连接ASM问题
    错误ORA-29760: instance_number parameter not specified的解决办法
    window phone webclient xml 乱码解决方法
    谈谈layout-weight
    状态栏更改颜色
    android 顶部导航栏
    android 布局抽取优化
    Kotlin版HelloWorld
    浅谈synchronized作用
    android获取Tomcat的JSON数据
  • 原文地址:https://www.cnblogs.com/notlate/p/10093071.html
Copyright © 2020-2023  润新知