前言
之前一段時(shí)間,準(zhǔn)備把糗百的項(xiàng)目中json解析的模塊中的原生Json解析換成gson解析,工作比較繁雜,坑多,因此為了防止出錯(cuò),我還對(duì)Gson做了一個(gè)源碼分析。這一篇就是Gson源碼分析的總結(jié),同時(shí)對(duì)Gson內(nèi)部運(yùn)用的設(shè)計(jì)模式也進(jìn)行了總結(jié),相信了解了它的源碼和運(yùn)行機(jī)制,對(duì)于使用Gson的使用會(huì)更有幫助。
Gson簡(jiǎn)介
Gson,就是幫助我們完成序列化和反序列化的工作的一個(gè)庫(kù)。
- 日常用法
UserInfo userInfo = getUserInfo();
Gson gson = new Gson();
String jsonStr = gson.toJson(userInfo); // 序列化
UserInfo user = gson.fromJson(jsonStr,UserInfo.class); // 反序列化
實(shí)際上我們用的最多的是Gson的反序列化,主要在解析服務(wù)器返回的json串。因此,后面的文章也會(huì)以Gson中的反序列化的過程為主來(lái)分析代碼。
在分析之前,我們先做個(gè)簡(jiǎn)單的猜想,要如何實(shí)現(xiàn)反序列化的流程的,Gson大體會(huì)做一下這三件事:
- 反射創(chuàng)建該類型的對(duì)象
- 把json中對(duì)應(yīng)的值賦給對(duì)象對(duì)應(yīng)的屬性
- 返回該對(duì)象。
事實(shí)上,Gson想要把json數(shù)據(jù)反序列化基本都逃不掉這三個(gè)步驟,但是這三個(gè)步驟就像小品里分三步把大象裝進(jìn)冰箱一樣。我們知道最復(fù)雜的一步就是把大象裝進(jìn)去,畢竟,開冰箱門或者關(guān)冰箱門大家都會(huì)的嘛。在Gson中,復(fù)雜的就是怎樣把json中對(duì)應(yīng)數(shù)據(jù)放入對(duì)應(yīng)的屬性中。而這個(gè)問題的答案就是Gson的TypeAdapter。
Gson核心:TypeAdapter
TypeAdapter是Gson的核心,它的意思是類型適配器,而說到適配器,大家都會(huì)想到適配器模式,沒錯(cuò),這個(gè)TypeAdapter的設(shè)計(jì)這確實(shí)是一個(gè)適配器模式,因?yàn)镴son數(shù)據(jù)接口和Type的接口兩者是無(wú)法兼容,因此TypeAdapter就是來(lái)實(shí)現(xiàn)兼容,把json數(shù)據(jù)讀到Type中,把Type中的數(shù)據(jù)寫入到Json里。
public abstract class TypeAdapter<T> {
// JsonWriter代表Json數(shù)據(jù),T則是對(duì)應(yīng)的Type的對(duì)象
public abstract void write(JsonWriter out, T value) throws IOException;
// JsonWriter代表Json數(shù)據(jù),T則是對(duì)應(yīng)的Type的對(duì)象
public abstract T read(JsonReader in) throws IOException;
...
...
...
}
簡(jiǎn)單而言,TypeAdapter的作用就是針對(duì)Type進(jìn)行適配,保證把json數(shù)據(jù)讀到Type中,或者把Type中的數(shù)據(jù)寫入到Json里
Type和TypeAdapter的對(duì)應(yīng)關(guān)系
Gson會(huì)為每一種類型創(chuàng)建一個(gè)TypeAdapter,同樣的,每一個(gè)Type都對(duì)應(yīng)唯一一個(gè)TypeAdapter
而所有Type(類型),在Gson中又可以分為基本類型和復(fù)合類型(非基本類型)
- 基本類型(Integer,String,Uri,Url,Calendar...):這里的基本類型不僅包括Java的基本數(shù)據(jù)類型,還有很多其他的數(shù)據(jù)類型
- 復(fù)合類型(非基本類型):即除了基本類型之外的類型,往往是我們自定義的一些業(yè)務(wù)相關(guān)的JavaBean,比如User,Article.....等等。
這里的基本類型和復(fù)合類型(非基本類型)是筆者定義的詞匯,因?yàn)檫@樣定義對(duì)于讀者理解Gson源碼和運(yùn)行機(jī)制更有幫助。
如上圖,每一種基本類型都會(huì)創(chuàng)建一個(gè)TypeAdapter來(lái)適配它們,而所有的復(fù)合類型(即我們自己定義的各種JavaBean)都會(huì)由ReflectiveTypeAdapter來(lái)完成適配
TypeAdapter和Gson運(yùn)行機(jī)制
既然講到了每種Type都有對(duì)應(yīng)的TypeAdapter,那么為什么說TypeAdapter是Gson的核心呢?我們可以看看Gson到底是如何實(shí)現(xiàn)Json解析的呢,下圖是Gson完成json解析的抽象簡(jiǎn)化的流程圖:
如上圖,如果是基本類型,那么對(duì)應(yīng)的TypeAdapter就可以直接讀寫Json串,如果是復(fù)合類型,ReflectiveTypeAdapter會(huì)反射創(chuàng)建該類型的對(duì)象,并逐個(gè)分析其內(nèi)部的屬性的類型,然后重復(fù)上述工作。直至所有的屬性都是Gson認(rèn)定的基本類型并完成讀寫工作。
TypeAdapter源碼分析
當(dāng)類型是復(fù)合類型的時(shí)候,Gson會(huì)創(chuàng)建ReflectiveTypeAdapter,我們可以看看這個(gè)Adapter的源碼:
// 創(chuàng)建ReflectiveTypeAdapter
new Adapter<T>(constructor, getBoundFields(gson, type, raw));
...
...
/**
* ReflectiveTypeAdapter是ReflectiveTypeAdapterFactory的內(nèi)部類,其實(shí)際的類名就是Adapter
* 本文只是為了區(qū)別其他的TypeAdapter而叫它 ReflectiveTypeAdapter
**/
public static final class Adapter<T> extends TypeAdapter<T> {
// 該復(fù)合類型的構(gòu)造器,用于反射創(chuàng)建對(duì)象
private final ObjectConstructor<T> constructor;
// 該類型內(nèi)部的所有的Filed屬性,都通過map存儲(chǔ)起來(lái)
private final Map<String, BoundField> boundFields;
Adapter(ObjectConstructor<T> constructor, Map<String, BoundField> boundFields) {
this.constructor = constructor;
this.boundFields = boundFields;
}
//JsonReader是Gson封裝的對(duì)Json相關(guān)的操作類,可以依次讀取json數(shù)據(jù)
// 類似的可以參考Android封裝的對(duì)XML數(shù)據(jù)解析的操作類XmlPullParser
@Override public T read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
T instance = constructor.construct();
try {
in.beginObject(); // 從“{”開始讀取
while (in.hasNext()) {
String name = in.nextName(); //開始逐個(gè)讀取json串中的key
BoundField field = boundFields.get(name); // 通過key尋找對(duì)應(yīng)的屬性
if (field == null || !field.deserialized) {
in.skipValue();
} else {
field.read(in, instance); // 將json串的讀取委托給了各個(gè)屬性
}
}
} catch (IllegalStateException e) {
throw new JsonSyntaxException(e);
} catch (IllegalAccessException e) {
throw new AssertionError(e);
}
in.endObject(); // 到對(duì)應(yīng)的“}”結(jié)束
return instance;
}
...
...
}
Gson內(nèi)部并沒有ReflectiveTypeAdapter這個(gè)類,它其實(shí)際上是ReflectiveTypeAdapterFactory類一個(gè)名叫Adapter的內(nèi)部類,叫它ReflectiveTypeAdapter是為了表意明確。
我們看到,ReflectiveTypeAdapter內(nèi)部會(huì)首先創(chuàng)建該類型的對(duì)象,然后遍歷該對(duì)象內(nèi)部的所有屬性,接著把json傳的讀去委托給了各個(gè)屬性。
被委托的BoundField內(nèi)部又是如何做的呢?BoundField這個(gè)類,是對(duì)Filed相關(guān)操作的封裝,我們來(lái)看看BoundField是如何創(chuàng)建的,以及內(nèi)部的工作原理。
// 創(chuàng)建ReflectiveTypeAdapter getBoundFields獲取該類型所有的屬性
new Adapter<T>(constructor, getBoundFields(gson, type, raw));
...
...
private Map<String, BoundField> getBoundFields(Gson context, TypeToken<?> type, Class<?> raw) {
// 創(chuàng)建一個(gè)Map結(jié)構(gòu),存放所有的BoundField
Map<String, BoundField> result = new LinkedHashMap<String, BoundField>();
if (raw.isInterface()) {
return result;
}
Type declaredType = type.getType();
while (raw != Object.class) { // 如果類型是Object則結(jié)束循環(huán)
Field[] fields = raw.getDeclaredFields(); // 獲取該類型的所有的內(nèi)部屬性
for (Field field : fields) {
boolean serialize = excludeField(field, true);
boolean deserialize = excludeField(field, false);
if (!serialize && !deserialize) {
continue;
}
accessor.makeAccessible(field);
Type fieldType = $Gson$Types.resolve(type.getType(), raw, field.getGenericType());
List<String> fieldNames = getFieldNames(field); // 獲取該Filed的名字(Gson通過注解可以給一個(gè)屬性多個(gè)解析名)
BoundField previous = null;
for (int i = 0, size = fieldNames.size(); i < size; ++i) {
String name = fieldNames.get(i);
// 多個(gè)解析名,第一作為默認(rèn)的序列化名稱
if (i != 0) serialize = false; // only serialize the default name
// 創(chuàng)建BoundField
BoundField boundField = createBoundField(context, field, name,
TypeToken.get(fieldType), serialize, deserialize);
// 將BoundField放入Map中,獲取被替換掉的value(如果有的話)
BoundField replaced = result.put(name, boundField);
// 做好記錄
if (previous == null) previous = replaced;
}
if (previous != null) {
// 如果previous != null證明出現(xiàn)了兩個(gè)相同的Filed name,直接拋出錯(cuò)誤
// 注:Gson不允許定義兩個(gè)相同的名稱的屬性(父類和子類之間可能出現(xiàn))
throw new IllegalArgumentException(declaredType
+ " declares multiple JSON fields named " + previous.name);
}
}
type = TypeToken.get($Gson$Types.resolve(type.getType(), raw, raw.getGenericSuperclass()));
raw = type.getRawType(); // 獲取父類類型,最終會(huì)索引到Object.因?yàn)镺bject是所有對(duì)象的父類
}
return result;
}
上面這段代碼的主要工作就是,找到該類型內(nèi)部的所有屬性,并嘗試逐一封裝成BoundField。
// 根據(jù)每個(gè)Filed創(chuàng)建BoundField(封裝Filed讀寫操作)
private ReflectiveTypeAdapterFactory.BoundField createBoundField(
final Gson context, final Field field, final String name,
final TypeToken<?> fieldType, boolean serialize, boolean deserialize) {
// 是否是原始數(shù)據(jù)類型 (int,boolean,float...)
final boolean isPrimitive = Primitives.isPrimitive(fieldType.getRawType());
...
...
if (mapped == null){
// Gson嘗試獲取該類型的TypeAdapter,這個(gè)方法我們后面也會(huì)繼續(xù)提到。
mapped = context.getAdapter(fieldType);
}
// final變量,便于內(nèi)部類使用
final TypeAdapter<?> typeAdapter = mapped;
return new ReflectiveTypeAdapterFactory.BoundField(name, serialize, deserialize) {
...
...
// ReflectiveTypeAdapter委托的Json讀操作會(huì)調(diào)用到這里
@Override void read(JsonReader reader, Object value)
throws IOException, IllegalAccessException {
// 通過該屬性的類型對(duì)應(yīng)的TypeAdapter嘗試讀取json串
//如果是基礎(chǔ)類型,則直接讀取,
//如果是復(fù)合類型則遞歸之前的流程
Object fieldValue = typeAdapter.read(reader);
if (fieldValue != null || !isPrimitive) {
field.set(value, fieldValue); //更新filed值
}
}
@Override public boolean writeField(Object value) throws IOException, IllegalAccessException {
if (!serialized) return false;
Object fieldValue = field.get(value);
return fieldValue != value; // avoid recursion for example for Throwable.cause
}
};
}
假設(shè)該復(fù)合類型中所有的屬性的類型是String,則屬性所對(duì)應(yīng)的TypeAdapter以及其讀寫方式如下:
public static final TypeAdapter<String> STRING = new TypeAdapter<String>() {
@Override
public String read(JsonReader in) throws IOException {
JsonToken peek = in.peek(); // 獲取下一個(gè)jsontoken而不消耗它
if (peek == JsonToken.NULL) {
in.nextNull();
return null;
}
/* coerce booleans to strings for backwards compatibility */
if (peek == JsonToken.BOOLEAN) {
return Boolean.toString(in.nextBoolean()); // 如果時(shí)布爾值,則轉(zhuǎn)化為String
}
return in.nextString(); // 從json串中獲取這個(gè)String類型的value并消耗它
}
@Override
public void write(JsonWriter out, String value) throws IOException {
out.value(value); // 不做任何處理直接寫入Json串
}
}
到這里,關(guān)于Gson的TypeAdapter的原理也就講得差不多了,回顧一下,因?yàn)門ype有兩類,對(duì)應(yīng)的TypeAdapter也有兩類,一類是ReflectiveTypeAdapter,針對(duì)復(fù)合類型,它的作用是把復(fù)合類型拆解成基本類型,另一類是針對(duì)基本類型的TypeAdapter,實(shí)現(xiàn)對(duì)應(yīng)基本類型的Json串讀寫工作。而Gson本質(zhì)上就是按照這兩類TypeAdapter來(lái)完成Json解析的。
可以說,到這里,我們現(xiàn)在對(duì)Gson的基本工作流程有了一個(gè)基本的認(rèn)識(shí)。
再一次分析Gson的執(zhí)行邏輯
事實(shí)上,文章到這里結(jié)合上面的源碼剖析和簡(jiǎn)化流程圖,我們已經(jīng)可以比較比較真實(shí)的分析出Gson的執(zhí)行邏輯了。
Gson反序列化的日常用法:
UserInfo userInfo = getUserInfo();
Gson gson = new Gson();
String jsonStr = getJsonData();
UserInfo user = gson.fromJson(jsonStr,UserInfo.class); // 反序列化
gson.fromJson(jsonStr,UserInfo.class)方法內(nèi)部真實(shí)的代碼執(zhí)行流程大致如下:
- 對(duì)jsonStr,UserInfo.class這兩個(gè)數(shù)據(jù)進(jìn)行封裝
- 通過UserInfo.class這個(gè)Type來(lái)獲取它對(duì)應(yīng)的TypeAdapter
- 拿到對(duì)應(yīng)的TypeAdapter(ReflectiveTypeAdapterFactor),并執(zhí)行讀取json的操作
- 返回UserInfo這個(gè)類型的對(duì)象。
我們描述的這個(gè)流程和Gson代碼真實(shí)的執(zhí)行流程已經(jīng)沒太大的區(qū)別了。
TypeAdapter的創(chuàng)建與工廠模式
Gson中除了適配器模式之外最重要的設(shè)計(jì)模式,可能就是工廠模式吧。因?yàn)镚son中眾多的TypeAdapter都是通過工廠模式統(tǒng)一創(chuàng)建的:
public interface TypeAdapterFactory {
// 創(chuàng)建TypeAdapter的接口
<T> TypeAdapter<T> create(Gson gson, TypeToken<T> type);
}
我們可以看看ReflectiveTypeAdapterFactory的實(shí)現(xiàn)
// ReflectiveTypeAdapterFactory的實(shí)現(xiàn)
public final class ReflectiveTypeAdapterFactory implements TypeAdapterFactory {
@Override public <T> TypeAdapter<T> create(Gson gson, final TypeToken<T> type) {
Class<? super T> raw = type.getRawType();
// 只要是Object的子類,就能匹配上
if (!Object.class.isAssignableFrom(raw)) {
// it's a primitive!
return null;
}
ObjectConstructor<T> constructor = constructorConstructor.get(type);
return new Adapter<T>(constructor, getBoundFields(gson, type, raw));
}
}
Gson在其構(gòu)造方法中,就提前把所有的TypeAdapterFactory放在緩存列表中。
Gson(final Excluder excluder, final FieldNamingStrategy fieldNamingStrategy,
final Map<Type, InstanceCreator<?>> instanceCreators, boolean serializeNulls,
boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe,
boolean prettyPrinting, boolean lenient, boolean serializeSpecialFloatingPointValues,
LongSerializationPolicy longSerializationPolicy, String datePattern, int dateStyle,
int timeStyle, List<TypeAdapterFactory> builderFactories,
List<TypeAdapterFactory> builderHierarchyFactories,
List<TypeAdapterFactory> factoriesToBeAdded) {
...
...
...
List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>();
// built-in type adapters that cannot be overridden
factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);
factories.add(ObjectTypeAdapter.FACTORY);
// the excluder must precede all adapters that handle user-defined types
factories.add(excluder);
// users type adapters
factories.addAll(factoriesToBeAdded);
// type adapters for basic platform types
factories.add(TypeAdapters.STRING_FACTORY);
factories.add(TypeAdapters.INTEGER_FACTORY);
factories.add(TypeAdapters.BOOLEAN_FACTORY);
factories.add(TypeAdapters.BYTE_FACTORY);
factories.add(TypeAdapters.SHORT_FACTORY);
TypeAdapter<Number> longAdapter = longAdapter(longSerializationPolicy);
factories.add(TypeAdapters.newFactory(long.class, Long.class, longAdapter));
factories.add(TypeAdapters.newFactory(double.class, Double.class,
doubleAdapter(serializeSpecialFloatingPointValues)));
factories.add(TypeAdapters.newFactory(float.class, Float.class,
floatAdapter(serializeSpecialFloatingPointValues)));
factories.add(TypeAdapters.NUMBER_FACTORY);
factories.add(TypeAdapters.ATOMIC_INTEGER_FACTORY);
factories.add(TypeAdapters.ATOMIC_BOOLEAN_FACTORY);
factories.add(TypeAdapters.newFactory(AtomicLong.class, atomicLongAdapter(longAdapter)));
factories.add(TypeAdapters.newFactory(AtomicLongArray.class, atomicLongArrayAdapter(longAdapter)));
factories.add(TypeAdapters.ATOMIC_INTEGER_ARRAY_FACTORY);
factories.add(TypeAdapters.CHARACTER_FACTORY);
factories.add(TypeAdapters.STRING_BUILDER_FACTORY);
factories.add(TypeAdapters.STRING_BUFFER_FACTORY);
factories.add(TypeAdapters.newFactory(BigDecimal.class, TypeAdapters.BIG_DECIMAL));
factories.add(TypeAdapters.newFactory(BigInteger.class, TypeAdapters.BIG_INTEGER));
factories.add(TypeAdapters.URL_FACTORY);
factories.add(TypeAdapters.URI_FACTORY);
factories.add(TypeAdapters.UUID_FACTORY);
factories.add(TypeAdapters.CURRENCY_FACTORY);
factories.add(TypeAdapters.LOCALE_FACTORY);
factories.add(TypeAdapters.INET_ADDRESS_FACTORY);
factories.add(TypeAdapters.BIT_SET_FACTORY);
factories.add(DateTypeAdapter.FACTORY);
factories.add(TypeAdapters.CALENDAR_FACTORY);
factories.add(TimeTypeAdapter.FACTORY);
factories.add(SqlDateTypeAdapter.FACTORY);
factories.add(TypeAdapters.TIMESTAMP_FACTORY);
factories.add(ArrayTypeAdapter.FACTORY);
factories.add(TypeAdapters.CLASS_FACTORY);
// type adapters for composite and user-defined types
factories.add(new CollectionTypeAdapterFactory(constructorConstructor));
factories.add(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization));
this.jsonAdapterFactory = new JsonAdapterAnnotationTypeAdapterFactory(constructorConstructor);
factories.add(jsonAdapterFactory);
factories.add(TypeAdapters.ENUM_FACTORY);
// 注意,ReflectiveTypeAdapterFactor是要最后添加的
factories.add(new ReflectiveTypeAdapterFactory(
constructorConstructor, fieldNamingStrategy, excluder, jsonAdapterFactory));
this.factories = Collections.unmodifiableList(factories);
}
這里我們能夠看到,ReflectiveTypeAdapterFactor最后被添加進(jìn)去的,因?yàn)檫@里的添加順序是有講究的。我們看看getAdapter(type)方法就能知道。
getAdapter(type)這個(gè)方法就是gson通過type尋找到對(duì)應(yīng)的TypeAdapter,這是Gson中非常重要的一個(gè)方法。
// 通過Type獲取TypeAdapter
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
try {
// 遍歷緩存中所有的TypeAdapterFactory,
for (TypeAdapterFactory factory : factories) {
//如果類型匹配,則create()將會(huì)返回一個(gè)TypeAdapter,否則為nulll
TypeAdapter<T> candidate = factory.create(this, type);
if (candidate != null) {
// candidate不為null,證明找到類型匹配的TypeAdapter.
return candidate;
}
}
throw new IllegalArgumentException("GSON (" + GsonBuildConfig.VERSION + ") cannot handle " + type);
}
}
ReflectiveTypeAdapterFactory之所以在緩存列表的最后一個(gè),就是因?yàn)樗芷ヅ鋷缀跞魏晤愋?/strong>,因此,我們?yōu)橐粋€(gè)類型遍歷時(shí),只能先判斷它是不是基本類型,如果都不成功,最后再使用ReflectiveTypeAdapterFactor進(jìn)行判斷。
這就是Gson中用到的工廠模式。
關(guān)于代碼的難點(diǎn)
我們重新回到getAdapter(type)這個(gè)方法,這個(gè)方法里面有一些比較難理解的代碼
// 通過Type獲取TypeAdapter
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
// typeTokenCache是Gson的一個(gè)Map類型的緩存結(jié)構(gòu)
// 0,首先嘗試從緩存中獲取是否有對(duì)應(yīng)的TypeAdapter
TypeAdapter<?> cached = typeTokenCache.get(type == null ? NULL_KEY_SURROGATE : type);
if (cached != null) {
return (TypeAdapter<T>) cached;
}
// 1,alls 是Gson內(nèi)部的ThreadLocal變量,用于保存一個(gè)Map對(duì)象
// map對(duì)象也緩存了一種FutureTypeAdapter
Map<TypeToken<?>, FutureTypeAdapter<?>> threadCalls = calls.get();
boolean requiresThreadLocalCleanup = false;
if (threadCalls == null) {
threadCalls = new HashMap<TypeToken<?>, FutureTypeAdapter<?>>();
calls.set(threadCalls);
requiresThreadLocalCleanup = true;
}
//2,如果從ThreadLocal內(nèi)部的Map中找到緩存,則直接返回
// the key and value type parameters always agree
FutureTypeAdapter<T> ongoingCall = (FutureTypeAdapter<T>) threadCalls.get(type);
if (ongoingCall != null) {
return ongoingCall;
}
try {
創(chuàng)建一個(gè)FutureTypeAdapter
FutureTypeAdapter<T> call = new FutureTypeAdapter<T>();
// 緩存
threadCalls.put(type, call);
for (TypeAdapterFactory factory : factories) {
// 遍歷所有的TypeAdapterFactory
TypeAdapter<T> candidate = factory.create(this, type);
if (candidate != null) {
// 3, 設(shè)置委托的TypeAdapter
call.setDelegate(candidate);
// 緩存到Gson內(nèi)部的Map中,
typeTokenCache.put(type, candidate);
return candidate;
}
}
//如果遍歷都沒有找到對(duì)應(yīng)的TypeAdapter,直接拋出異常
throw new IllegalArgumentException("GSON (" + GsonBuildConfig.VERSION + ") cannot handle " + type);
} finally {
// 4,移除threadCalls內(nèi)部緩存的 FutureTypeAdapter
threadCalls.remove(type);
if (requiresThreadLocalCleanup) {
//ThreadLocal移除該線程環(huán)境中的Map
calls.remove();
}
}
}
上述代碼比較難以理解的地方我標(biāo)注了序號(hào),用于后面解釋代碼
方法里出現(xiàn)了FutureTypeAdapter這個(gè)TypeAdapter,似乎很奇怪,因?yàn)樗鼪]有FutureTypeAdapterFactory這個(gè)工廠類,我們先來(lái)看看 FutureTypeAdapter的內(nèi)部構(gòu)造
static class FutureTypeAdapter<T> extends TypeAdapter<T> {
private TypeAdapter<T> delegate;
public void setDelegate(TypeAdapter<T> typeAdapter) {
if (delegate != null) {
throw new AssertionError();
}
delegate = typeAdapter;
}
@Override public T read(JsonReader in) throws IOException {
if (delegate == null) {
throw new IllegalStateException();
}
return delegate.read(in);
}
@Override public void write(JsonWriter out, T value) throws IOException {
if (delegate == null) {
throw new IllegalStateException();
}
delegate.write(out, value);
}
}
這是一個(gè)明顯的委派模式(也可稱為代理模式)的包裝類。我們都知道委托模式的功能是:隱藏代碼具體實(shí)現(xiàn),通過組合的方式同樣的功能,避開繼承帶來(lái)的問題。但是在這里使用委派模式似乎并不是基于這些考慮。而是為了避免陷入無(wú)限遞歸導(dǎo)致對(duì)棧溢出的崩潰。
為什么這么說呢?我們來(lái)舉個(gè)例子:
// 定義一個(gè)帖子的實(shí)體
public class Article {
// 表示帖子中鏈接到其他的帖子
public Article linkedArticle;
.....
.....
.....
}
Article類型中有一個(gè)linkedArticle屬性,它的類型還是Article,根據(jù)我們之前總結(jié)的簡(jiǎn)化流程圖:
你會(huì)發(fā)現(xiàn)這里有一個(gè)死循環(huán),或者說無(wú)法終結(jié)的遞歸。為了避免這個(gè)問題,所以先創(chuàng)建一個(gè)代理類,等到遞歸遇到同樣的類型時(shí)直接復(fù)用返回,避免無(wú)限遞歸。也就是注釋2那段代碼的用意,在注釋3處,再將創(chuàng)建成功的TypeAdapter設(shè)置到代理類中。就基本解決這個(gè)問題了。
當(dāng)然說基本解決,是因?yàn)檫€要考慮多線程的環(huán)境,所以就出現(xiàn)了ThreadLocal這個(gè)線程局部變量,這保證了它只會(huì)在單個(gè)線程中緩存,而且會(huì)在單次Json解析完成后移出緩存。見上文注釋1和注釋4。這是因?yàn)闊o(wú)限遞歸只會(huì)發(fā)生在單次Json解析中,而且Gson內(nèi)部已經(jīng)有了一個(gè)TypeAdapterde 全局緩存(typeTokenCache),見注釋0.
潛在的遞歸循環(huán): gson.getAdapter(type) ---> (ReflectiveTypeAdapterFactory)factory.create(this, type) ---> getBoundFields() ---> createBoundField() ---> (Gson)context.getAdapter(fieldType)
關(guān)于Gson自定義解析
上文只講到了Gson自己內(nèi)部是如何實(shí)現(xiàn)Json解析的,其實(shí)Gson也提供了一些自定義解析的接口。主要是兩種:
- 自己實(shí)現(xiàn)繼承TypeAdapter
- 實(shí)現(xiàn)JsonSerializer/JsonDeserializer接口
那么,兩者有什么區(qū)別呢?
追求效率更高,選第一種,想要操作更簡(jiǎn)單,實(shí)現(xiàn)更靈活,選第二種。
為什么這么說?舉個(gè)例子,假設(shè)我們需要為Article這個(gè)JavaBean自定義解析,如果我們選擇繼承TypeAdapter的話,需要先實(shí)現(xiàn)TypeAdapter,然后注冊(cè)。
// 繼承TypeAdapter,實(shí)現(xiàn)抽象方法
public class ArticleTypeAdapter extends TypeAdapter<Article>{
@Override
public void write(JsonWriter out, Article value) throws IOException {
// 實(shí)現(xiàn)把Article中的實(shí)體數(shù)據(jù)的寫入到JsonWriter中,實(shí)現(xiàn)序列化
}
@Override
public Article read(JsonReader in) throws IOException {
// 需要?jiǎng)?chuàng)建Article對(duì)象
// 把 JsonReader中的json串讀出來(lái),并設(shè)置到Article對(duì)象中
return null;
}
}
...
...
// 注冊(cè)
Gson mGson = new GsonBuilder()
.registerTypeAdapter(Article.class, new ArticleTypeAdapter<>())//實(shí)際上注冊(cè)到Gson的factories列表中
.create();
這樣就實(shí)現(xiàn)了自定義的Json解析,這種方式的讀寫效率很高,但是不太靈活,因?yàn)楸仨氁瑫r(shí)實(shí)現(xiàn)序列化和反序列化的工作。
而實(shí)現(xiàn)JsonSerializer/JsonDeserializer接口這種方式相對(duì)更簡(jiǎn)單
//JsonSerializer(json序列話)/JsonDeserializer(反序列化)可按需實(shí)現(xiàn)
public class ArticleTypeAdapter implements JsonDeserializer<Article> {
@Override
public Article deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
// 需要?jiǎng)?chuàng)建Article對(duì)象
// 并從JsonElement中把封裝好的Json數(shù)據(jù)結(jié)構(gòu)讀出來(lái),并設(shè)置到Article對(duì)象中
return null;
}
}
// 注冊(cè)
Gson mGson = new GsonBuilder()
.registerTypeAdapter(Article.class, new ArticleTypeAdapter<>())//實(shí)際上注冊(cè)到Gson的factories列表中
.create();
我們可以看到,兩者的區(qū)別,是后者更加靈活,序列化/返序列化可按需選擇,而且它使用了JsonElement對(duì)Json數(shù)據(jù)進(jìn)行再封裝,從而使我們操作Json數(shù)據(jù)更加簡(jiǎn)單。不過正是因?yàn)槭褂昧?JsonElement這種對(duì)Json數(shù)據(jù)再封裝的類,而不是更加原始的JsonReader導(dǎo)致了代碼執(zhí)行效率的降低。
如上圖所示,本質(zhì)上就是多了一個(gè)中間層,導(dǎo)致解析效率的降低。不過話說回來(lái),只要不是非常大批量復(fù)雜結(jié)構(gòu)的連續(xù)解析,這種效率差異我們可以忽略不計(jì),因此日常的開發(fā),大家通過JsonSerializer/JsonDeserializer接口來(lái)實(shí)現(xiàn)自定義解析是一個(gè)相對(duì)更好的選擇。