Dubbo之PojoUtils源码分析

功能概述

  • PojoUtils是一个工具类,能够进行深度遍历,将简单类型与复杂类型的对象进行转换,在泛化调用时用到(在泛化调用中,主要将Pojo对象与Map对象进行相互转换)

功能分析

核心类PojoUtils分析

主要成员变量分析

private static final ConcurrentMap<String, Method> NAME_METHODS_CACHE = new ConcurrentHashMap<String, Method>(); //方法名与Method的缓存(为了减少反射获取Method调用),key的值用类名和参数类型拼接,如:"org.apache.dubbo.common.model.Person.setName(java.lang.String)"
private static final ConcurrentMap<Class<?>, ConcurrentMap<String, Field>> CLASS_FIELD_CACHE = new ConcurrentHashMap<Class<?>, ConcurrentMap<String, Field>>(); //字段所在类Class、字段名、字段信息Filed的缓存

主要成员方法分析

generalize将复杂对象转换为简单对象
private static Object generalize(Object pojo, Map<Object, Object> history) { //pojo对象的成员属性(会递归转换,pojo=》Map,直到所有属性为dubbo定义的基本类型)
    if (pojo == null) {
        return null;
    }

    if (pojo instanceof Enum<?>) {
        return ((Enum<?>) pojo).name(); //枚举类型,输出枚举的名称
    }
    if (pojo.getClass().isArray() && Enum.class.isAssignableFrom(pojo.getClass().getComponentType())) { //处理Enum数组
        int len = Array.getLength(pojo);
        String[] values = new String[len];
        for (int i = 0; i < len; i++) { //枚举数组会转换为String数组,数组元素的值为枚举名
            values[i] = ((Enum<?>) Array.get(pojo, i)).name();
        }
        return values;
    }

    if (ReflectUtils.isPrimitives(pojo.getClass())) { //基本类型直接返回,不做处理
        return pojo;
    }

    if (pojo instanceof Class) { //Class类的实例,返回类名称
        return ((Class) pojo).getName();
    }

    Object o = history.get(pojo);
    if (o != null) {
        return o;
    }
    history.put(pojo, pojo);

    if (pojo.getClass().isArray()) { //pojo对象为数组类型
        int len = Array.getLength(pojo);
        Object[] dest = new Object[len];
        history.put(pojo, dest);
        for (int i = 0; i < len; i++) {
            Object obj = Array.get(pojo, i);
            dest[i] = generalize(obj, history);
        }
        return dest;
    }
    if (pojo instanceof Collection<?>) { //pojo对象为集合类型
        Collection<Object> src = (Collection<Object>) pojo;
        int len = src.size();
        Collection<Object> dest = (pojo instanceof List<?>) ? new ArrayList<Object>(len) : new HashSet<Object>(len); //区分出List或Set类型,并创建对应的集合实例
        history.put(pojo, dest);
        for (Object obj : src) { //遍历集合元素,依次将元素进行转换
            dest.add(generalize(obj, history));
        }
        return dest;
    }
    if (pojo instanceof Map<?, ?>) { //pojo对象为Map类型
        Map<Object, Object> src = (Map<Object, Object>) pojo;
        Map<Object, Object> dest = createMap(src); //根据原Map类型,创建对应的Map对象
        history.put(pojo, dest);
        for (Map.Entry<Object, Object> obj : src.entrySet()) {
            dest.put(generalize(obj.getKey(), history), generalize(obj.getValue(), history)); //key、value都可能是pojo对象,所以都需要进行转换
        }
        return dest;
    }
    Map<String, Object> map = new HashMap<String, Object>();
    history.put(pojo, map);
    if (GENERIC_WITH_CLZ) {
        map.put("class", pojo.getClass().getName()); //设置pojo对象的Class类
    }
    for (Method method : pojo.getClass().getMethods()) {
        if (ReflectUtils.isBeanPropertyReadMethod(method)) { //判断是否读取bean的方法(即get/is方法)
            try {
                /**
                 * 处理步骤:
                 * 1)从方法名中获取到属性名
                 * 2)调用pojo对应的方法获取值,并通过generalize转换(传入history是做临时缓存,若能从history取到则用之)
                 * 3)将属性名和值设置到map中
                 */
                map.put(ReflectUtils.getPropertyNameFromBeanReadMethod(method), generalize(method.invoke(pojo), history));
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage(), e);
            }
        }
    }
    // public field
    for (Field field : pojo.getClass().getFields()) {
        if (ReflectUtils.isPublicInstanceField(field)) { //判断是否是公共的实例字段
            try {
                Object fieldValue = field.get(pojo);
                if (history.containsKey(pojo)) {
                    Object pojoGeneralizedValue = history.get(pojo); //已经转换过的字段,就不再转换
                    if (pojoGeneralizedValue instanceof Map
                            && ((Map) pojoGeneralizedValue).containsKey(field.getName())) {
                        continue;
                    }
                }
                if (fieldValue != null) {
                    map.put(field.getName(), generalize(fieldValue, history));
                }
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage(), e);
            }
        }
    }
    return map;
}
  • 代码分析:generalize方法的作用是把复杂类型对象转换为简单类型的对象,如将Pojo对象转换为Map对象,Pojo对象的成员对象若还是复杂类型,会递归调用进行转换。
realize将简单对象转换为复杂对象
private static Object realize0(Object pojo, Class<?> type, Type genericType, final Map<Object, Object> history) { //将简单类型转换为复杂类型(如:将Map对象转换为指定类型的pojo对象,将Map的属性值,通过set方法设置到pojo对象中,type为目标类型)
    if (pojo == null) {
        return null;
    }

    if (type != null && type.isEnum() && pojo.getClass() == String.class) { //将String转换为枚举类型
        return Enum.valueOf((Class<Enum>) type, (String) pojo);
    }

    if (ReflectUtils.isPrimitives(pojo.getClass())
            && !(type != null && type.isArray()
            && type.getComponentType().isEnum()
            && pojo.getClass() == String[].class)) { //将String数组转换为枚举数组
        return CompatibleTypeUtils.compatibleTypeConvert(pojo, type);
    }

    Object o = history.get(pojo); //history:当方法在递归调用时,会用到(用缓存使用)

    if (o != null) {
        return o;
    }

    history.put(pojo, pojo);

        if (pojo.getClass().isArray()) { //处理数组类型的pojo
            if (Collection.class.isAssignableFrom(type)) { //目标类型是集合类型
                Class<?> ctype = pojo.getClass().getComponentType(); //获取数组元素的类型
                int len = Array.getLength(pojo); //获取数组对应长度
                Collection dest = createCollection(type, len);
                history.put(pojo, dest);
                for (int i = 0; i < len; i++) {
                    Object obj = Array.get(pojo, i); //返回数组中指定下标的值
                    Object value = realize0(obj, ctype, null, history); //依次将对象转换为目标类型,如Map转换为pojo类型
                    dest.add(value);
                }
                return dest;
            } else {
                Class<?> ctype = (type != null && type.isArray() ? type.getComponentType() : pojo.getClass().getComponentType());
                int len = Array.getLength(pojo);
                Object dest = Array.newInstance(ctype, len);
                history.put(pojo, dest);
                for (int i = 0; i < len; i++) {
                    Object obj = Array.get(pojo, i);
                    Object value = realize0(obj, ctype, null, history);
                    Array.set(dest, i, value);
                }
                return dest;
            }
        }

        if (pojo instanceof Collection<?>) { //处理集合类型的pojo
            if (type.isArray()) { //集合转换为数组
                Class<?> ctype = type.getComponentType();
                Collection<Object> src = (Collection<Object>) pojo;
                int len = src.size();
                Object dest = Array.newInstance(ctype, len); //创建指定类型和长度的数组
                history.put(pojo, dest);
                int i = 0;
                for (Object obj : src) {
                    Object value = realize0(obj, ctype, null, history); //将数组中的元素依次转换为指定类型pojo对象
                    Array.set(dest, i, value);
                    i++;
                }
                return dest;
            } else {
                Collection<Object> src = (Collection<Object>) pojo;
                int len = src.size();
                Collection<Object> dest = createCollection(type, len);
                history.put(pojo, dest);
                for (Object obj : src) { //遍历集合元素,依次转化到目标类型的pojo对象
                    Type keyType = getGenericClassByIndex(genericType, 0);
                    Class<?> keyClazz = obj == null ? null : obj.getClass();
                    if (keyType instanceof Class) {
                        keyClazz = (Class<?>) keyType;
                    }
                    Object value = realize0(obj, keyClazz, keyType, history);
                    dest.add(value);
                }
                return dest;
            }
        }

        if (pojo instanceof Map<?, ?> && type != null) { //处理Map类型的pojo(JSONObject:JSON对象,实现了Map接口,也属于Map的实例对象,所以会进入此处)
            Object className = ((Map<Object, Object>) pojo).get("class"); //获取Map中的"class"键对应的值,是在generalize方法中设置的(单个的pojo中设置的)
            if (className instanceof String) {
                try {
                    type = ClassUtils.forName((String) className); //解析的目标类的Class类
                } catch (ClassNotFoundException e) {
                    // ignore
                }
            }

            // special logic for enum
            if (type.isEnum()) { //目标类型为枚举
                Object name = ((Map<Object, Object>) pojo).get("name"); //取出枚举名称
                if (name != null) {
                    return Enum.valueOf((Class<Enum>) type, name.toString()); //使用枚举名,构建枚举对象
                }
            }
            Map<Object, Object> map;
            // when return type is not the subclass of return type from the signature and not an interface
            if (!type.isInterface() && !type.isAssignableFrom(pojo.getClass())) { //type非接口且pojo不是type的子类型
                try {
                    map = (Map<Object, Object>) type.newInstance();
                    Map<Object, Object> mapPojo = (Map<Object, Object>) pojo;
                    map.putAll(mapPojo);
                    if (GENERIC_WITH_CLZ) {
                        map.remove("class");
                    }
                } catch (Exception e) {
                    //ignore error
                    map = (Map<Object, Object>) pojo; //type类型不为Map时,使用原始的pojo转换
                }
            } else {
                map = (Map<Object, Object>) pojo; //直接强转为Map类型
            }

            if (Map.class.isAssignableFrom(type) || type == Object.class) { //解析的目标类为Map时
                final Map<Object, Object> result;
                // fix issue#5939
                Type mapKeyType = getKeyTypeForMap(map.getClass()); //获取key的泛型参数对应的实际类型
                Type typeKeyType = getGenericClassByIndex(genericType, 0); //获取目标类型的泛型参数的第一个实际参数
                boolean typeMismatch = mapKeyType instanceof Class //Type为Class实例时,表明是基本类型或原始类型,如String、int等
                        && typeKeyType instanceof Class
                        && !typeKeyType.getTypeName().equals(mapKeyType.getTypeName()); //判断key、value类型为基本类型或原始类型,且类型相同
                if (typeMismatch) { //输入对象的key与目标Map的key类型不匹配是,创建新的Map
                    result = createMap(new HashMap(0));
                } else {
                    result = createMap(map); //类型匹配时,直接使用目标Map(会转换为具体的Map类型,如:转换为LinkedHashMap类型)
                }

                history.put(pojo, result);
                for (Map.Entry<Object, Object> entry : map.entrySet()) {
                    Type keyType = getGenericClassByIndex(genericType, 0); //获取泛型参数列表指定位置的实际类型
                    Type valueType = getGenericClassByIndex(genericType, 1);
                    Class<?> keyClazz; //获取key参数类型对应的Class
                    if (keyType instanceof Class) { //基本类型或原始类型(如:int、Boolean、String等)
                        keyClazz = (Class<?>) keyType;
                    } else if (keyType instanceof ParameterizedType) { //参数化类型(如:List<ArrayList<String>> 是泛型参数,取实际类型后为ArrayList<String>,实际参数属于参数类型)
                        keyClazz = (Class<?>) ((ParameterizedType) keyType).getRawType();
                    } else { //keyType为Null时,取条目中key的类型(其它类型,如类型变量类型T、通配符类型?等)
                        keyClazz = entry.getKey() == null ? null : entry.getKey().getClass();
                    }
                    Class<?> valueClazz; //获取value参数类型对应的Class
                    if (valueType instanceof Class) {
                        valueClazz = (Class<?>) valueType;
                    } else if (valueType instanceof ParameterizedType) {
                        valueClazz = (Class<?>) ((ParameterizedType) valueType).getRawType();
                    } else {
                        valueClazz = entry.getValue() == null ? null : entry.getValue().getClass();
                    }

                    Object key = keyClazz == null ? entry.getKey() : realize0(entry.getKey(), keyClazz, keyType, history); //递归调用,将key转换为目标类型的对象
                    Object value = valueClazz == null ? entry.getValue() : realize0(entry.getValue(), valueClazz, valueType, history); //递归调用,将value转换为目标类型的对象
                    result.put(key, value);
                }
                return result;
            } else if (type.isInterface()) { //解析的目标类为接口时,产生接口对应的代理类
                Object dest = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[] {type}, new PojoInvocationHandler(map)); //使用jdk代理机制为接口创代理对象,并指定处理器PojoInvocationHandler,在接口方法被调用时,就会触发处理器中方法执行指定逻辑
                history.put(pojo, dest);
                return dest;
            } else {
                Object dest = newInstance(type); //构造解析的目标类的实例
                history.put(pojo, dest); //设置到缓存Map中
                for (Map.Entry<Object, Object> entry : map.entrySet()) { //遍历Map中的条目,找到对应目标对象的属性,使用反射机制调用Method,依次设置值
                    Object key = entry.getKey();
                    if (key instanceof String) { //只处理key为String的条目
                        String name = (String) key;
                        Object value = entry.getValue();
                        if (value != null) {
                            Method method = getSetterMethod(dest.getClass(), name, value.getClass()); //通过属性获取set方法(从缓存中获取,若没有则通过反射获取Method,再设置到缓存中)
                            Field field = getField(dest.getClass(), name); //获取属性对应的字段Filed信息
                            if (method != null) {
                                if (!method.isAccessible()) {
                                    method.setAccessible(true);
                                }
                                Type ptype = method.getGenericParameterTypes()[0]; //获取set方法的第一个参数类型
                                value = realize0(value, method.getParameterTypes()[0], ptype, history); //将值转换为指定类型的对象
                                try {
                                    method.invoke(dest, value); //使用反射机制,设置目标对象的属性值
                                } catch (Exception e) {
                                    String exceptionDescription = "Failed to set pojo " + dest.getClass().getSimpleName() + " property " + name
                                            + " value " + value + "(" + value.getClass() + "), cause: " + e.getMessage();
                                    logger.error(exceptionDescription, e);
                                    throw new RuntimeException(exceptionDescription, e);
                                }
                            } else if (field != null) {
                                value = realize0(value, field.getType(), field.getGenericType(), history);
                                try {
                                    field.set(dest, value);
                                } catch (IllegalAccessException e) {
                                    throw new RuntimeException("Failed to set field " + name + " of pojo " + dest.getClass().getName() + " : " + e.getMessage(), e);
                                }
                            }
                        }
                    }
                }
                if (dest instanceof Throwable) { //目标对象为异常对象时,设置异常信息
                    Object message = map.get("message");
                    if (message instanceof String) {
                        try {
                            Field field = Throwable.class.getDeclaredField("detailMessage");
                            if (!field.isAccessible()) {
                                field.setAccessible(true);
                            }
                            field.set(dest, message);
                        } catch (Exception e) {
                        }
                    }
                }
                return dest;
            }
        }
        return pojo;
    }

关联类PojoInvocationHandler分析

类中核心代码分析
private static class PojoInvocationHandler implements InvocationHandler { //Pojo代理处理器

    private Map<Object, Object> map; //在创建代理对象时指定的

    public PojoInvocationHandler(Map<Object, Object> map) {
        this.map = map;
    }

    @Override
    @SuppressWarnings("unchecked")
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //为接口生成代理对象,在调用接口方法时,会回调该方法
        if (method.getDeclaringClass() == Object.class) {
            return method.invoke(map, args);
        }
        String methodName = method.getName();
        Object value = null;
        if (methodName.length() > 3 && methodName.startsWith("get")) {
            value = map.get(methodName.substring(3, 4).toLowerCase() + methodName.substring(4)); //截取方法名,获取属性名,从map中获取相应的值
        } else if (methodName.length() > 2 && methodName.startsWith("is")) {
            value = map.get(methodName.substring(2, 3).toLowerCase() + methodName.substring(3));
        } else {
            value = map.get(methodName.substring(0, 1).toLowerCase() + methodName.substring(1));
        }
        if (value instanceof Map<?, ?> && !Map.class.isAssignableFrom(method.getReturnType())) { //返回类型非Map时,调用realize0进行转换
            value = realize0((Map<String, Object>) value, method.getReturnType(), null, new IdentityHashMap<Object, Object>());
        }
        return value;
    }
}
  • 代码分析:在转换的目标类型为接口时type.isInterface(),使用jdk动态代理创建接口的代理对象,PojoInvocationHandler为代理对象的调用处理器,包含了提取属性的逻辑

问题点答疑

  • 在realize、generalize方法中都包含了参数Map<Object, Object> history,用途是什么?
    • 解答:在Pojo属性为复杂类型时,即需要递归转换或解析时,就可以把已经处理过的结果放入Map中,传递给下一个转换或解析。下次处理前,会判断是否已经处理过,处理过的就不再处理。这样已经处理过的类型就不用处理了,提升处理性能。

归纳总结

  • PojoUtils转换中,简单类型包含:基本类型、Number、Date、元素为基本类型的数组、集合类型等。
  • 在类型转换时,会进行递归调用,一直解析到位简单类型为止。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值