2021SC@SDUSC
本文在CSDN个人博客同步发出,地址CSDN博客
概要
上篇fastjson源码解析——反序列化(三)详细介绍了fastjson如何创建无反序列化实例类的反序列化实例,介绍了如何通过java.lang.reflect
查询到所有的Getter/Setter方法。
本期是一个特辑,专门介绍反序列化接口实现方法中,对已知类型类的反序列化实例的内部注册。
正式开始
在上期中,我提到了 对不同的Getter/Setter做处理,并且保存信息返回反序列化的上层函数。
承接上期,我详细介绍对不同类型类反序列化实例的内部注册
若所涉及的类型为:
已注册的类型
fastjson在内部已经注册了常用类型的反序列化实现方案,根据源代码注册的函数initDeserialize()
代码如下:
这部分代码可以完全不看,直接看我下面整理的表格即可看到清晰的对应关系(由代码一一查找)
private void initDeserializers() {
deserializers.put(SimpleDateFormat.class, MiscCodec.instance);
deserializers.put(Calendar.class, CalendarCodec.instance);
deserializers.put(XMLGregorianCalendar.class, CalendarCodec.instance);
deserializers.put(JSONObject.class, MapDeserializer.instance);
deserializers.put(JSONArray.class, CollectionCodec.instance);
deserializers.put(Map.class, MapDeserializer.instance);
deserializers.put(HashMap.class, MapDeserializer.instance);
deserializers.put(LinkedHashMap.class, MapDeserializer.instance);
deserializers.put(TreeMap.class, MapDeserializer.instance);
deserializers.put(ConcurrentMap.class, MapDeserializer.instance);
deserializers.put(ConcurrentHashMap.class, MapDeserializer.instance);
deserializers.put(Collection.class, CollectionCodec.instance);
deserializers.put(List.class, CollectionCodec.instance);
deserializers.put(ArrayList.class, CollectionCodec.instance);
deserializers.put(Object.class, JavaObjectDeserializer.instance);
deserializers.put(String.class, StringCodec.instance);
deserializers.put(StringBuffer.class, StringCodec.instance);
deserializers.put(StringBuilder.class, StringCodec.instance);
deserializers.put(char.class, CharacterCodec.instance);
deserializers.put(Character.class, CharacterCodec.instance);
deserializers.put(byte.class, NumberDeserializer.instance);
deserializers.put(Byte.class, NumberDeserializer.instance);
deserializers.put(short.class, NumberDeserializer.instance);
deserializers.put(Short.class, NumberDeserializer.instance);
deserializers.put(int.class, IntegerCodec.instance);
deserializers.put(Integer.class, IntegerCodec.instance);
deserializers.put(long.class, LongCodec.instance);
deserializers.put(Long.class, LongCodec.instance);
deserializers.put(BigInteger.class, BigIntegerCodec.instance);
deserializers.put(BigDecimal.class, BigDecimalCodec.instance);
deserializers.put(float.class, FloatCodec.instance);
deserializers.put(Float.class, FloatCodec.instance);
deserializers.put(double.class, NumberDeserializer.instance);
deserializers.put(Double.class, NumberDeserializer.instance);
deserializers.put(boolean.class, BooleanCodec.instance);
deserializers.put(Boolean.class, BooleanCodec.instance);
deserializers.put(Class.class, MiscCodec.instance);
deserializers.put(char[].class, new CharArrayCodec());
deserializers.put(AtomicBoolean.class, BooleanCodec.instance);
deserializers.put(AtomicInteger.class, IntegerCodec.instance);
deserializers.put(AtomicLong.class, LongCodec.instance);
deserializers.put(AtomicReference.class, ReferenceCodec.instance);
deserializers.put(WeakReference.class, ReferenceCodec.instance);
deserializers.put(SoftReference.class, ReferenceCodec.instance);
deserializers.put(UUID.class, MiscCodec.instance);
deserializers.put(TimeZone.class, MiscCodec.instance);
deserializers.put(Locale.class, MiscCodec.instance);
deserializers.put(Currency.class, MiscCodec.instance);
deserializers.put(Inet4Address.class, MiscCodec.instance);
deserializers.put(Inet6Address.class, MiscCodec.instance);
deserializers.put(InetSocketAddress.class, MiscCodec.instance);
deserializers.put(File.class, MiscCodec.instance);
deserializers.put(URI.class, MiscCodec.instance);
deserializers.put(URL.class, MiscCodec.instance);
deserializers.put(Pattern.class, MiscCodec.instance);
deserializers.put(Charset.class, MiscCodec.instance);
deserializers.put(JSONPath.class, MiscCodec.instance);
deserializers.put(Number.class, NumberDeserializer.instance);
deserializers.put(AtomicIntegerArray.class, AtomicCodec.instance);
deserializers.put(AtomicLongArray.class, AtomicCodec.instance);
deserializers.put(StackTraceElement.class, StackTraceElementDeserializer.instance);
deserializers.put(Serializable.class, JavaObjectDeserializer.instance);
deserializers.put(Cloneable.class, JavaObjectDeserializer.instance);
deserializers.put(Comparable.class, JavaObjectDeserializer.instance);
deserializers.put(Closeable.class, JavaObjectDeserializer.instance);
deserializers.put(JSONPObject.class, new JSONPDeserializer());
ModuleUtil.callWhenHasJavaSql(initDeserializersWithJavaSql);
}
以下是我根据上述代码整理的对应表格
注册的类型 | 反序列化实例 | 是否支持序列化 | 是否支持反序列化 |
---|---|---|---|
SimpleDateFormat | MiscCodec | 是 | 是 |
Calendar | CalendarCodec | 是 | 是 |
XMLGregorianCalendar | CalendarCodec | 是 | 是 |
JSONObject | MapDeserializer | - | 是 |
JSONArray | CollectionCodec | 是 | 是 |
**Map | MapDeserializer | - | 是 |
Collection | CollectionCodec | 是 | 是 |
List | CollectionCodec | 是 | 是 |
ArrayList | CollectionCodec | 是 | 是 |
Object | JavaObjectDeserializer | - | 是 |
String | StringCodec | 是 | 是 |
StringBuffer | StringCodec | 是 | 是 |
StringBuilder | StringCodec | 是 | 是 |
char/Character | CharacterCodec | 是 | 是 |
byte/Byte | NumberDeserializer | - | 是 |
short/Short | NumberDeserializer | - | 是 |
int/Integer | IntegerCodec | 是 | 是 |
long/Long | LongCodec | 是 | 是 |
BigInteger | BigIntegerCodec | 是 | 是 |
BigDecimal | BigDecimalCodec | 是 | 是 |
float/Float | FloatCodec | 是 | 是 |
double/Double | NumberDeserializer | - | 是 |
boolean/Boolean | BooleanCodec | 是 | 是 |
Class | MiscCodec | 是 | 是 |
char[] | CharArrayCodec | - | 是 |
Atomic* | *Codec | 随*的属性 | |
WeakReference | ReferenceCodec | 是 | 是 |
SoftReference | ReferenceCodec | 是 | 是 |
UUID/TimeZone/Locale/Currency | MiscCodec | 是 | 是 |
Inet4/6/SocketAddress | MiscCodec | 是 | 是 |
File/URI/URL | MiscCodec | 是 | 是 |
Pattern/Charset/JSONPath | MiscCodec | 是 | 是 |
Serializable | JavaObjectDeserializer | - | 是 |
Cloneable | JavaObjectDeserializer | - | 是 |
Comparable | JavaObjectDeserializer | - | 是 |
Closeable | JavaObjectDeserializer | - | 是 |
JSONPObject | JSONPDeserializer | - | 是 |
通过先在内部注册不同类型的序列化/反序列化实例,可以让fastjson在运行时能够查找到特定的反序列化实例而不需要使用默认Java的反序列化实例。
从我整理的这张表,能看出3个问题:
-
几乎所有的类型都有已经存在的反序列化实例
-
fastjson放弃部分类的序列化实现,但是仍然保留了这些类的反序列化操作
个人推测,fastjson没有实现序列化的这部分类太过于复杂,内部字段过多,或者这些类没有遵守JavaBean的标准,其内部并没有Getter/Setter方法
-
通过查看反序列化实例中,包含
Codec
字段的类,可发现这些类都是对应类型的序列化实例。fastjson中序列化实例都同时实现了反序列化的操作,且内部注册的类型极多。若发送方使用fastjson序列化生成JSONString
,接收方调用反序列化操作时,可以保证“谁序列化,谁也执行反序列化操作”这一特点,在保证稳定性的同时,大大降低了程序间的耦合性,极大减少了程序员维护代码的成本代价。若后续发现某类型的反序列化实例出现bug,可以针对性地对某个实例debug,不需要牵涉到其他任何实例。
总而言之,这样的程序设计逻辑,保证了fastjson极高的性能,较低的程序后期维护成本。
上一期我们见识到了如何规范代码,提高代码可读性。这一期,我们又可以窥探到阿里巴巴开发者对程序耦合性细致入微的把握。通过遍历、细分所有Java常见类,先行注册反序列化实例,提高性能,又因为仔细分类,使用序列化实例完成反序列化操作,降低耦合度,提高稳定性。
我自己认为,我还写不出具有这样性能与稳定性同时提高的优化逻辑的代码。这说明以后我们该学习的还有很多,还需要慢慢提高自己
最后
fastjson反序列化的部分暂时介绍到这里。特辑一详细罗列了fastjson内部所有已注册的反序列化实例(实际上是序列化实例)。下一步我将继续深入,解读每一个反序列化实例内部对token的使用(token的详情可以参考我的同学的文章:Fastjson源码分析—反序列化—Token的定义和解析(1))
下一期,特辑将继续,对几个主要的反序列化实例(BooleanCodec
,CharacterCodec
,IntegerCodec
,FloatCodec
,JavaBeanDeserializer
)的实现逻辑展开分析
感谢各位老师的阅读与指导!