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();  
相关推荐
王元_SmallA20 分钟前
Redis Desktop Manager(Redis可视化工具)安装
java·后端
ᐇ95923 分钟前
Java HashMap深度解析:数据结构、原理与实战指南
java·开发语言·数据结构
好好研究26 分钟前
Spring框架 - 开发方式
java·后端·spring
武子康42 分钟前
Java-166 Neo4j 安装与最小闭环 | 10 分钟跑通 + 远程访问 Docker neo4j.conf
java·数据库·sql·docker·系统架构·nosql·neo4j
2301_796512521 小时前
Rust编程学习 - 为什么说Cow 代表的是Copy-On-Write, 即“写时复制技术”,它是一种高效的 资源管理手段
java·学习·rust
编啊编程啊程1 小时前
【029】智能停车计费系统
java·数据库·spring boot·spring·spring cloud·kafka
hashiqimiya1 小时前
springboot后端的接口headers
java·spring boot·后端
懒羊羊不懒@2 小时前
JavaSe—集合框架、Collection集合
java·开发语言
隐语SecretFlow2 小时前
新晋社区之星何晨阳:从使用者到贡献者,我是如何理解并反哺开源?
程序人生·开源·开源软件