赞
踩
2021SC@SDUSC
在上一篇文章中,我们浅析了writeJSONString一个大致的处理顺序以及它的代码结构和作用,字符流输出的大致结构和它相仿,所以我们更加关注字节流及字符流的更加深入的实现.
我们在上一篇文章中提到过关于ObjectSerializer这个接口,它的主要作用便是提供了write方法接口来帮助具体类实现序列化的功能.也就是对应的如下代码:
- Class<?> clazz = object.getClass();//获取对象的class元信息
- ObjectSerializer writer = getObjectWriter(clazz);//初始化对象序列化器
-
- try {
- writer.write(this, object, null, null, 0);//调用write方法
- } catch (IOException e) {
- throw new JSONException(e.getMessage(), e);
- }
本篇内容将会关注于该类的具体实现类的获取方式.
我们主要分析的源码是SerializeConfig的结构以及getObjectWriter具体的实现方法.
在上一篇中我们知道了,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的内容,这不是本篇重点),我们注意到最后一段代码,调用对象序列化器的初始化方法,这里直接上源码:
- private void initSerializers() {
- put(Boolean.class, BooleanCodec.instance);
- put(Character.class, CharacterCodec.instance);
- put(Byte.class, IntegerCodec.instance);
- put(Short.class, IntegerCodec.instance);
- put(Integer.class, IntegerCodec.instance);
- put(Long.class, LongCodec.instance);
- put(Float.class, FloatCodec.instance);
- put(Double.class, DoubleSerializer.instance);
- put(BigDecimal.class, BigDecimalCodec.instance);
- put(BigInteger.class, BigIntegerCodec.instance);
- put(String.class, StringCodec.instance);
- put(byte[].class, PrimitiveArraySerializer.instance);
- put(short[].class, PrimitiveArraySerializer.instance);
- put(int[].class, PrimitiveArraySerializer.instance);
- put(long[].class, PrimitiveArraySerializer.instance);
- put(float[].class, PrimitiveArraySerializer.instance);
- put(double[].class, PrimitiveArraySerializer.instance);
- put(boolean[].class, PrimitiveArraySerializer.instance);
- put(char[].class, PrimitiveArraySerializer.instance);
- put(Object[].class, ObjectArrayCodec.instance);
- put(Class.class, MiscCodec.instance);
-
- put(SimpleDateFormat.class, MiscCodec.instance);
- put(Currency.class, new MiscCodec());
- put(TimeZone.class, MiscCodec.instance);
- put(InetAddress.class, MiscCodec.instance);
- put(Inet4Address.class, MiscCodec.instance);
- put(Inet6Address.class, MiscCodec.instance);
- put(InetSocketAddress.class, MiscCodec.instance);
- put(File.class, MiscCodec.instance);
- put(Appendable.class, AppendableSerializer.instance);
- put(StringBuffer.class, AppendableSerializer.instance);
- put(StringBuilder.class, AppendableSerializer.instance);
- put(Charset.class, ToStringSerializer.instance);
- put(Pattern.class, ToStringSerializer.instance);
- put(Locale.class, ToStringSerializer.instance);
- put(URI.class, ToStringSerializer.instance);
- put(URL.class, ToStringSerializer.instance);
- put(UUID.class, ToStringSerializer.instance);
-
- // atomic
- put(AtomicBoolean.class, AtomicCodec.instance);
- put(AtomicInteger.class, AtomicCodec.instance);
- put(AtomicLong.class, AtomicCodec.instance);
- put(AtomicReference.class, ReferenceCodec.instance);
- put(AtomicIntegerArray.class, AtomicCodec.instance);
- put(AtomicLongArray.class, AtomicCodec.instance);
-
- put(WeakReference.class, ReferenceCodec.instance);
- put(SoftReference.class, ReferenceCodec.instance);
-
- put(LinkedList.class, CollectionCodec.instance);
- }

这个方法应该是将map给初始化了,这里就直接用java提供的基本数据类型和常用数据类型的class,以及所对应的Codec实例(instance)组成键值对放入map中,这里就可以简单知道各种Codec的实例就是实现好的ObjectSerializer了.我们先将codec放在一边,回过来再看我们的getObjectSerializer方法,这个方法的名字直接表明了就是要返回一个对象序列化器,这个方法的直接实现方法为:
这个方法的代码量较大,但是可以很好地按照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不需要每次用过后就再初始化,这样做既顾及了效率,同时也具有泛用性.下一篇我们将更加深入了解序列化的实现机制.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。