当前位置:   article > 正文

fastJSON源码分析_2_对象序列化器的获取_fastjson2 objectserializer

fastjson2 objectserializer

2021SC@SDUSC

 本篇简介

上一篇文章中,我们浅析了writeJSONString一个大致的处理顺序以及它的代码结构和作用,字符流输出的大致结构和它相仿,所以我们更加关注字节流及字符流的更加深入的实现.

我们在上一篇文章中提到过关于ObjectSerializer这个接口,它的主要作用便是提供了write方法接口来帮助具体类实现序列化的功能.也就是对应的如下代码:

  1. Class<?> clazz = object.getClass();//获取对象的class元信息
  2. ObjectSerializer writer = getObjectWriter(clazz);//初始化对象序列化器
  3. try {
  4. writer.write(this, object, null, null, 0);//调用write方法
  5. } catch (IOException e) {
  6. throw new JSONException(e.getMessage(), e);
  7. }

本篇内容将会关注于该类的具体实现类的获取方式.

源码分析

我们主要分析的源码是SerializeConfig的结构以及getObjectWriter具体的实现方法.

SerializeConfig

在上一篇中我们知道了,ObjectSrializer的具体实现类的获取是根据getObjectWriter(Class)来初始化的.

getObjectWriter方法是由JSONSerializer类所维护的SerializeConfig来实现的,当我们在调用writeJSONString方法的时候,SerializeConfig是作为了该方法的一个参数类型,而该参数默认是一个静态的值SerializeConfig.globalInstance,也就是全局定义的一个配置实例.

我们去看SerializeConfig的内容,其实globalInstance就是一个无参的SerializeConfig对象.

 但是无参的构造函数最终又调用了有参的构造函数,参数分别为tableSize:int,和fieldBase:boolean.

 我们可以看到,SerilizeConfig维护了两个map,也就是重新编写的IdentityHashMap,其中Serializers的大小为DEFAULT_SIZE(具体是8192),对应的key和value是<Type,ObjectSerializer>,可以很容易地猜到这是一个管理序列化器的map,而,mixInSerializers这个map则是一个管理这类map的map,大小为16.

这里我注意到了Type这个key类型,它是java反射库里定义的一个接口,是java所有的基本数据类型以及类所实现的接口,那为什么要用这样的类型作为key呢?往下看(跳过有关asm的内容,这不是本篇重点),我们注意到最后一段代码,调用对象序列化器的初始化方法,这里直接上源码:

  1. private void initSerializers() {
  2. put(Boolean.class, BooleanCodec.instance);
  3. put(Character.class, CharacterCodec.instance);
  4. put(Byte.class, IntegerCodec.instance);
  5. put(Short.class, IntegerCodec.instance);
  6. put(Integer.class, IntegerCodec.instance);
  7. put(Long.class, LongCodec.instance);
  8. put(Float.class, FloatCodec.instance);
  9. put(Double.class, DoubleSerializer.instance);
  10. put(BigDecimal.class, BigDecimalCodec.instance);
  11. put(BigInteger.class, BigIntegerCodec.instance);
  12. put(String.class, StringCodec.instance);
  13. put(byte[].class, PrimitiveArraySerializer.instance);
  14. put(short[].class, PrimitiveArraySerializer.instance);
  15. put(int[].class, PrimitiveArraySerializer.instance);
  16. put(long[].class, PrimitiveArraySerializer.instance);
  17. put(float[].class, PrimitiveArraySerializer.instance);
  18. put(double[].class, PrimitiveArraySerializer.instance);
  19. put(boolean[].class, PrimitiveArraySerializer.instance);
  20. put(char[].class, PrimitiveArraySerializer.instance);
  21. put(Object[].class, ObjectArrayCodec.instance);
  22. put(Class.class, MiscCodec.instance);
  23. put(SimpleDateFormat.class, MiscCodec.instance);
  24. put(Currency.class, new MiscCodec());
  25. put(TimeZone.class, MiscCodec.instance);
  26. put(InetAddress.class, MiscCodec.instance);
  27. put(Inet4Address.class, MiscCodec.instance);
  28. put(Inet6Address.class, MiscCodec.instance);
  29. put(InetSocketAddress.class, MiscCodec.instance);
  30. put(File.class, MiscCodec.instance);
  31. put(Appendable.class, AppendableSerializer.instance);
  32. put(StringBuffer.class, AppendableSerializer.instance);
  33. put(StringBuilder.class, AppendableSerializer.instance);
  34. put(Charset.class, ToStringSerializer.instance);
  35. put(Pattern.class, ToStringSerializer.instance);
  36. put(Locale.class, ToStringSerializer.instance);
  37. put(URI.class, ToStringSerializer.instance);
  38. put(URL.class, ToStringSerializer.instance);
  39. put(UUID.class, ToStringSerializer.instance);
  40. // atomic
  41. put(AtomicBoolean.class, AtomicCodec.instance);
  42. put(AtomicInteger.class, AtomicCodec.instance);
  43. put(AtomicLong.class, AtomicCodec.instance);
  44. put(AtomicReference.class, ReferenceCodec.instance);
  45. put(AtomicIntegerArray.class, AtomicCodec.instance);
  46. put(AtomicLongArray.class, AtomicCodec.instance);
  47. put(WeakReference.class, ReferenceCodec.instance);
  48. put(SoftReference.class, ReferenceCodec.instance);
  49. put(LinkedList.class, CollectionCodec.instance);
  50. }

这个方法应该是将map给初始化了,这里就直接用java提供的基本数据类型和常用数据类型的class,以及所对应的Codec实例(instance)组成键值对放入map中,这里就可以简单知道各种Codec的实例就是实现好的ObjectSerializer了.我们先将codec放在一边,回过来再看我们的getObjectSerializer方法,这个方法的名字直接表明了就是要返回一个对象序列化器,这个方法的直接实现方法为:

getObjectSerializer(clazz,create)

这个方法的代码量较大,但是可以很好地按照clazz的类型进行分类,

1.首先从初始化的基本类型序列化器map中寻找对应的序列化器,如果有,就直接返回.否则再继续判断.

2. 紧接着判断该clazz是否是自动装配对象的基本类型,这里的类加载器分别使用了当前线程的类加载器以及当前类(JSON)的类加载器

 3.接着是判断是否是Module中存在的clazz,这个是一个扩展模块,可以编写自己需要的序列化器模块

 4.然后是更加多类型的序列化器的判断(主要是接口类型及其实现),包括数组,列表,map,枚举类型等等.这里只上部分代码.

 isAssignablleFrom方法的含义是判(Class)是否是调用对象(Class)的接口或者父类.

5.再往下就是关于各种库的类型的支持包括awt,jdk8,jdbc等等.

总而言之

有关对象序列化器的获取框架就是通过对象的class类型,创建config对象,通过判断从维护的map中获取到相应的对象序列化实例,然后处理对象.不过序列化器map的组织方式有着很鲜明的特点,就是先放一点常用的数据类型让我们去取它们的序列化器,而不是全部在初始化时就放入map中,然后再通过进一步的判断,将clazz对应的序列化器动态地生成放入map中,再取出返回,并且由于config是静态的对象,map不需要每次用过后就再初始化,这样做既顾及了效率,同时也具有泛用性.下一篇我们将更加深入了解序列化的实现机制.

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/爱喝兽奶帝天荒/article/detail/997928
推荐阅读
相关标签
  

闽ICP备14008679号