Fastjson源码分析—ParserConfig的作用及原理(2)

本文详细剖析ParserConfig的getDeserializer, createJavaBeanDeserializer和initJavaBeanDeserializers方法,揭示Fastjson如何通过这些函数实现自定义序列化过程,提升灵活性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2021SC@SDUSC
上一篇我们分析了ParserConfig的使用方法、关键变量的含义以及checkAutoType方法ConfigFromPropety方法的解析,这篇文章我们继续分析ParserConfig的另外几个关键方法,深度了解它的作用原理。

getDeserializer(Type type)

该方法用于获取指定类型的反序列化器。反序列化匹配getDeserializer(Type)主要特定处理了泛型类型,取出泛型类型真实类型还是委托内部ParserConfig#getDeserializer(java.lang.Class<?>, java.lang.reflect.Type)进行精确类型查找。
先上代码:

 public ObjectDeserializer getDeserializer(Type type) {
        ObjectDeserializer deserializer = get(type);
        if (deserializer != null) {
            return deserializer;
        }

        if (type instanceof Class<?>) {
            return getDeserializer((Class<?>) type, type);
        }

        if (type instanceof ParameterizedType) {
            Type rawType = ((ParameterizedType) type).getRawType();
            if (rawType instanceof Class<?>) {
                return getDeserializer((Class<?>) rawType, type);
            } else {
                return getDeserializer(rawType);
            }
        }

        if (type instanceof WildcardType) {
            WildcardType wildcardType = (WildcardType) type;
            Type[] upperBounds = wildcardType.getUpperBounds();
            if (upperBounds.length == 1) {
                Type upperBoundType = upperBounds[0];
                return getDeserializer(upperBoundType);
            }
        }

        return JavaObjectDeserializer.instance;
    }

可以看到该方法的执行流程是:

  1. 首先从内部已经注册查找特定class的反序列化实例
  2. 如果是引用类型,根据特定类型再次匹配
  3. 获取泛型类型原始类型
  4. 如果泛型原始类型是引用类型,根据特定类型再次匹配
  5. 递归调用反序列化查找
  6. 如果类型是通配符或者限定类型,获取泛型上界,根据特定类型再次匹配
  7. 如果无法匹配到,使用默认JavaObjectDeserializer反序列化

createJavaBeanDeserializer

该方法用于创建特定javabean的反序列化器,先看看代码:

    public ObjectDeserializer createJavaBeanDeserializer(Class<?> clazz, Type type) {
        boolean asmEnable = this.asmEnable & !this.fieldBased;
        if (asmEnable) {
            JSONType jsonType = TypeUtils.getAnnotation(clazz,JSONType.class);

            if (jsonType != null) {
                Class<?> deserializerClass = jsonType.deserializer();
                if (deserializerClass != Void.class) {
                    try {
                        Object deseralizer = deserializerClass.newInstance();
                        if (deseralizer instanceof ObjectDeserializer) {
                            return (ObjectDeserializer) deseralizer;
                        }
                    } catch (Throwable e) {
                        // skip
                    }
                }

                asmEnable = jsonType.asm()
                        && jsonType.parseFeatures().length == 0;
            }

            if (asmEnable) {
                Class<?> superClass = JavaBeanInfo.getBuilderClass(clazz, jsonType);
                if (superClass == null) {
                    superClass = clazz;
                }

                for (;;) {
                    if (!Modifier.isPublic(superClass.getModifiers())) {
                        asmEnable = false;
                        break;
                    }

                    superClass = superClass.getSuperclass();
                    if (superClass == Object.class || superClass == null) {
                        break;
                    }
                }
            }
        }

        if (clazz.getTypeParameters().length != 0) {
            asmEnable = false;
        }

        if (asmEnable && asmFactory != null && asmFactory.classLoader.isExternalClass(clazz)) {
            asmEnable = false;
        }

        if (asmEnable) {
            asmEnable = ASMUtils.checkName(clazz.getSimpleName());
        }

        if (asmEnable) {
            if (clazz.isInterface()) {
                asmEnable = false;
            }
            JavaBeanInfo beanInfo = JavaBeanInfo.build(clazz
                    , type
                    , propertyNamingStrategy
                    ,false
                    , TypeUtils.compatibleWithJavaBean
                    , jacksonCompatible
            );

            if (asmEnable && beanInfo.fields.length > 200) {
                asmEnable = false;
            }

            Constructor<?> defaultConstructor = beanInfo.defaultConstructor;
            if (asmEnable && defaultConstructor == null && !clazz.isInterface()) {
                asmEnable = false;
            }

            for (FieldInfo fieldInfo : beanInfo.fields) {
                if (fieldInfo.getOnly) {
                    asmEnable = false;
                    break;
                }

                Class<?> fieldClass = fieldInfo.fieldClass;
                if (!Modifier.isPublic(fieldClass.getModifiers())) {
                    asmEnable = false;
                    break;
                }

                if (fieldClass.isMemberClass() && !Modifier.isStatic(fieldClass.getModifiers())) {
                    asmEnable = false;
                    break;
                }

                if (fieldInfo.getMember() != null //
                    && !ASMUtils.checkName(fieldInfo.getMember().getName())) {
                    asmEnable = false;
                    break;
                }

                JSONField annotation = fieldInfo.getAnnotation();
                if (annotation != null //
                    && ((!ASMUtils.checkName(annotation.name())) //
                        || annotation.format().length() != 0 //
                        || annotation.deserializeUsing() != Void.class //
                        || annotation.parseFeatures().length != 0 //
                        || annotation.unwrapped())
                        || (fieldInfo.method != null && fieldInfo.method.getParameterTypes().length > 1)) {
                    asmEnable = false;
                    break;
                }

                if (fieldClass.isEnum()) { // EnumDeserializer
                    ObjectDeserializer fieldDeser = this.getDeserializer(fieldClass);
                    if (!(fieldDeser instanceof EnumDeserializer)) {
                        asmEnable = false;
                        break;
                    }
                }
            }
        }

        if (asmEnable) {
            if (clazz.isMemberClass() && !Modifier.isStatic(clazz.getModifiers())) {
                asmEnable = false;
            }
        }

        if (asmEnable) {
            if (TypeUtils.isXmlField(clazz)) {
                asmEnable = false;
            }
        }

        if (!asmEnable) {
            return new JavaBeanDeserializer(this, clazz, type);
        }

        JavaBeanInfo beanInfo = JavaBeanInfo.build(clazz, type, propertyNamingStrategy);
        try {
            return asmFactory.createJavaBeanDeserializer(this, beanInfo);
            // } catch (VerifyError e) {
            // e.printStackTrace();
            // return new JavaBeanDeserializer(this, clazz, type);
        } catch (NoSuchMethodException ex) {
            return new JavaBeanDeserializer(this, clazz, type);
        } catch (JSONException asmError) {
            return new JavaBeanDeserializer(this, beanInfo);
        } catch (Exception e) {
            throw new JSONException("create asm deserializer error, " + clazz.getName(), e);
        }
    }

代码比较长,其中包括许多if分支,总结下来,这个方法主要做了这些事:
先确定是否使用asm。首先对asmEnable判断,如果是true,则使用asm的方式生成特定javabean的反序列化器,否则,使用常规的set方法进行反序列化(效率低、不安全)。
在确定使用asm的前提下,先判断要反序列化的类型JSONType,如果默认的反序列化解析器库中存在相应的解析器,那么调用相应的解析器。如果没有,则生成对应的解析器:先确定json字符串有哪些属性,然后构造对应的setter、getter,使用前几篇提到的asm方法直接生成class文件。

initJavaBeanDeserializers

讲完了Java bean构造器如何动态生成,就可以看看在如何对其进行初始化了。

public void initJavaBeanDeserializers(Class<?>... classes) {
        if (classes == null) {
            return;
        }

        for (Class<?> type : classes) {
            if (type == null) {
                continue;
            }
            ObjectDeserializer deserializer = createJavaBeanDeserializer(type, type);
            putDeserializer(type, deserializer);
        }
    }

首先对传入的class对象判断是否为空,如果为空,直接返回。不为空的话,一个一个对class对象判断其type,type若为空,跳过这一轮循环进入下一轮循环。不为空,则调用createJavaBeanDeserializer为其生成反序列化器,并将对应的type和反序列化器放入一个map容器中。

总结

这两篇着重分析了ParserConfig的关键方法的作用及其实现原理。ParserConfig的存在,使得Fastjson可以实现高度定制化,调用者可以自由地对Fastjson进行配置从而达到自己的目的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值