Gson源碼解析和它的設(shè)計(jì)模式

前言

之前一段時(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ì)更有幫助。

image

Gson簡(jiǎn)介

image

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里。

image
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ī)制更有幫助。

image

如上圖,每一種基本類型都會(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)化的流程圖:

image

如上圖,如果是基本類型,那么對(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解析的。


image

可以說,到這里,我們現(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)化流程圖:

image

你會(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.

image

潛在的遞歸循環(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í)行效率的降低。

image

如上圖所示,本質(zhì)上就是多了一個(gè)中間層,導(dǎo)致解析效率的降低。不過話說回來(lái),只要不是非常大批量復(fù)雜結(jié)構(gòu)的連續(xù)解析,這種效率差異我們可以忽略不計(jì),因此日常的開發(fā),大家通過JsonSerializer/JsonDeserializer接口來(lái)實(shí)現(xiàn)自定義解析是一個(gè)相對(duì)更好的選擇。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容