Gson加速器——自动生成TypeAdapter代码

Github地址:GsonEnhance

Overview

Gson 在序列化/反序列化过程,对于非内建类型,通过反射的手段来收集类对象的所有字段,额外的在反序列化过程通过反射来创建类实例,因此导致了序列化/反序列化过程的耗时性能问题。当然,Gson 也提供了一些接口让我们重写以规避反射:

  • TypeAdapter:自定义对象的序列化/反序列化过程
  • InstanceCreator:自定义创建对象实例
    GsonEnhance 利用上述特性,通过 APT 技术在编译时自动生成类对象相关的 TypeAdapter。目前提供了两个注解GsonTypeAdapterGsonNewInstance
  • GsonTypeAdapter:能够生成完整的 TypeAdpater 代码,对于使用了 GsonTypeAdapter 注解的类,无需再使用 GsonNewInstance 注解。
  • GsonNewInstance:自定义类对象创建,避免反射创建类实例。在移动端对于包大小有要求的情况下,TypeAdapter 生成的相关代码可能较多,因此退而求其次,减少反射创建类实例带来的性能影响。

Usage

GsonTypeAdapter

添加GsonTypeAdapter注解:

Java 复制代码
@GsonTypeAdapter  
public class GsonEnhanceModel {  
	@SerializedName(value = "int_value", alternate = {"alternate_int_value", "int_value_alternate"})  
	private int intValue;  
	private long longValue;  
	private float floatValue;

	public int getIntValue() {
        return intValue;
    }

    public void setIntValue(int intValue) {
        this.intValue = intValue;
    }

    public long getLongValue() {
        return longValue;
    }

    public void setLongValue(long longValue) {
        this.longValue = longValue;
    }

    public float getFloatValue() {
        return floatValue;
    }

    public void setFloatValue(float floatValue) {
        this.floatValue = floatValue;
    }
}

编译后会在同包名目录下生成关联的 TypeAdapter,以及配套的 GsonTypeAdapterFactory

Java 复制代码
public class GsonEnhanceModelTypeAdapter extends TypeAdapter<GsonEnhanceModel> {
  private Gson gson;

  private TypeAdapter<Integer> integerTypeAdapter;

  private TypeAdapter<Long> longTypeAdapter;

  private TypeAdapter<Float> floatTypeAdapter;

  public GsonEnhanceModelTypeAdapter(Gson gson) {
    this.gson = gson;
  }

  @Override
  public GsonEnhanceModel read(JsonReader jsonReader) throws IOException {
    GsonEnhanceModel deserializeValue = new GsonEnhanceModel();
    jsonReader.beginObject();
    while (jsonReader.hasNext()) {
      String jsonName = jsonReader.nextName();
      switch (jsonName) {
        case "int_value":
        case "alternate_int_value":
        case "int_value_alternate":
          int intValueInstance = getIntegerTypeAdapter().read(jsonReader);
          deserializeValue.setIntValue(intValueInstance);
          break;
        case "longValue":
          long longValueInstance = getLongTypeAdapter().read(jsonReader);
          deserializeValue.setLongValue(longValueInstance);
          break;
        case "floatValue":
          float floatValueInstance = getFloatTypeAdapter().read(jsonReader);
          deserializeValue.setFloatValue(floatValueInstance);
          break;
        default:
          jsonReader.skipValue();
          break;
      }
    }
    jsonReader.endObject();
    return deserializeValue;
  }

  @Override
  public void write(JsonWriter jsonWriter, GsonEnhanceModel value) throws IOException {
    if (value == null) {
      jsonWriter.nullValue();
      return;
    }
    jsonWriter.beginObject();
    jsonWriter.name("int_value");
    getIntegerTypeAdapter().write(jsonWriter, value.getIntValue());
    jsonWriter.name("longValue");
    getLongTypeAdapter().write(jsonWriter, value.getLongValue());
    jsonWriter.name("floatValue");
    getFloatTypeAdapter().write(jsonWriter, value.getFloatValue());
    jsonWriter.endObject();
  }

  public TypeAdapter<Integer> getIntegerTypeAdapter() {
    if(integerTypeAdapter == null) {
      integerTypeAdapter = (TypeAdapter<Integer>)gson.getAdapter(TypeToken.get(Integer.class));
    }
    return integerTypeAdapter;
  }

  public TypeAdapter<Long> getLongTypeAdapter() {
    if(longTypeAdapter == null) {
      longTypeAdapter = (TypeAdapter<Long>)gson.getAdapter(TypeToken.get(Long.class));
    }
    return longTypeAdapter;
  }

  public TypeAdapter<Float> getFloatTypeAdapter() {
    if(floatTypeAdapter == null) {
      floatTypeAdapter = (TypeAdapter<Float>)gson.getAdapter(TypeToken.get(Float.class));
    }
    return floatTypeAdapter;
  }
}

APT 生成关联的 TypeAdapterFactory, 名字固定为:GsonTypeAdapterFactory

Java 复制代码
public class GsonTypeAdapterFactory implements TypeAdapterFactory {
  @Override
  public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
    Class<? super T> clazz = type.getRawType();
    if (clazz == GsonEnhanceModel.class) {
      return (TypeAdapter<T>) new GsonEnhanceModelTypeAdapter(gson);
    }
    return null;
  }
}

使用时通过 GsonBuilder 创建 Gson 对象:

Java 复制代码
Gson gsonEnhance = (new GsonBuilder()).registerTypeAdapterFactory(new GsonTypeAdapterFactory()).create();  

GsonNewInstance

添加GsonNewInstance注解

Java 复制代码
@GsonNewInstance  
@GsonNewInstance
public class GsonEnhanceModel {
    ...
} 

编译后生成一个 registerInstanceCreator 方法,为每一个添加了注解的类生成对应的 createInstance 来避免对象实例化时的反射

Java 复制代码
public class GsonEnhance {
  public static void registerInstanceCreator(GsonBuilder gsonBuilder) {
    gsonBuilder.registerTypeAdapter(ObjectModel.class, new InstanceCreator<ObjectModel>() {
      @Override
      public ObjectModel createInstance(Type type) {
        return new ObjectModel();
      }
    });
  }
}

通过 GsonBuilder 注入 registerInstanceCreator 方法

Java 复制代码
GsonBuilder gsonBuilder = new GsonBuilder();  
GsonEnhance.registerInstanceCreator(gsonbuilder);  
Gson gson = gsonBuilder.create();  
相关推荐
Yaml430 分钟前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
小小小妮子~32 分钟前
Spring Boot详解:从入门到精通
java·spring boot·后端
hong16168834 分钟前
Spring Boot中实现多数据源连接和切换的方案
java·spring boot·后端
aloha_7891 小时前
从零记录搭建一个干净的mybatis环境
java·笔记·spring·spring cloud·maven·mybatis·springboot
记录成长java2 小时前
ServletContext,Cookie,HttpSession的使用
java·开发语言·servlet
睡觉谁叫~~~2 小时前
一文解秘Rust如何与Java互操作
java·开发语言·后端·rust
程序媛小果2 小时前
基于java+SpringBoot+Vue的旅游管理系统设计与实现
java·vue.js·spring boot
ClkLog-开源埋点用户分析2 小时前
ClkLog企业版(CDP)预售开启,更有鸿蒙SDK前来助力
华为·开源·开源软件·harmonyos
小屁孩大帅-杨一凡3 小时前
java后端请求想接收多个对象入参的数据
java·开发语言
java1234_小锋3 小时前
使用 RabbitMQ 有什么好处?
java·开发语言