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();  
相关推荐
_oP_i21 分钟前
Pinpoint 是一个开源的分布式追踪系统
java·分布式·开源
mmsx24 分钟前
android sqlite 数据库简单封装示例(java)
android·java·数据库
武子康1 小时前
大数据-258 离线数仓 - Griffin架构 配置安装 Livy 架构设计 解压配置 Hadoop Hive
java·大数据·数据仓库·hive·hadoop·架构
豪宇刘2 小时前
MyBatis的面试题以及详细解答二
java·servlet·tomcat
秋恬意2 小时前
Mybatis能执行一对一、一对多的关联查询吗?都有哪些实现方式,以及它们之间的区别
java·数据库·mybatis
FF在路上3 小时前
Knife4j调试实体类传参扁平化模式修改:default-flat-param-object: true
java·开发语言
真的很上进3 小时前
如何借助 Babel+TS+ESLint 构建现代 JS 工程环境?
java·前端·javascript·css·react.js·vue·html
众拾达人3 小时前
Android自动化测试实战 Java篇 主流工具 框架 脚本
android·java·开发语言
皓木.3 小时前
Mybatis-Plus
java·开发语言
不良人天码星3 小时前
lombok插件不生效
java·开发语言·intellij-idea