Gson源码解析之InstanceCreator简单说明

通过Gson的反射解析机制详解(1)Gson的反射解析机制详解(2)
这两篇博文我们知道Gson的通过反射工作的原理其实就是一句话:
根据Type遍历Class的Field属性,然后调用Field.set(obj,value)方法为一个属性赋值,其中obj是一个javabean的对象实例。

本篇就简单讲讲这个obj 在gson中是怎么初始化这个obj的。从中体会汲取Gson 优秀的设计理念。这里涉及到了InstanceCreator接口的使用。

public interface InstanceCreator<T> {
  public T createInstance(Type type);
}

该接口的作用也很简单,顾名思义就是对象创建者,就是根据传入的类型返回一个JavaBean对象,比如你可以这么使用(更多例子点击此处或者此处):

public void testInstanceCreatorReturnsBaseType(){
  Gson gson=new GsonBuilder().registerTypeAdapter(Base.class,new InstanceCreator<Base>(){
    public Base createInstance(    Type type){
      return new Base();
    }
  }
).create();

  String json="{baseName:'BaseRevised',subName:'Sub'}";
  Base base=gson.fromJson(json,Base.class);
  assertEquals("BaseRevised",base.baseName);
}

该结口的主要作用就是初始化File.setValue(obj,value)的中的这个obj,根据前面对Gson讲解的博文我们知道Gson在初始化对象的时候是由如下代码的(建议看博主的其他关于Gson的解析):

 //创建对象的实例:这段至关重要 参考《Gson反射解析机制详解(1)》
public T read(JsonReader in) throws IOException {
      //....
      //实例化一个对象
      T instance = constructor.construct();

        in.beginObject();
        //遍历json为instance的字段自动赋值
        while (in.hasNext()) {
          String name = in.nextName();
          BoundField field = boundFields.get(name);
          if (field == null || !field.deserialized) {
            in.skipValue();
          } else {
            field.read(in, instance);
          }
        }

      in.endObject();
      //返回一个java bean对象
      return instance;
    }

上述reader的方法的主要目的就是调用gson.fromJson(json,Base.class)的时候返回给你一个Base对象,该对象就是通过:

 T instance = constructor.construct();

来初始化的。

都到此处你可能会问,不是说javaBean的初始化是通过InstanceCreator接口的createInstance方法初始化的么?这个constructor.construct()是什么鬼?
带着着两个问题,先来看看InstanceCreator是怎么注入到Gson中的。

纵观一些常用的框架,构建着模式起到了很大的作用,常用的库都使用了构建者模式:EventBus,ImageLoader,Glide,Fresco,Okhttp等等等,Gson也不例外----GsonBuilder.
配置InstanceCreator的时候就是在GsonBuilder来配置的(见文章开头的例子)。在GsonBuilder中提供了registerTypeAdapter方法来注册用户自己的InstanceCreator:

 private final Map<Type, InstanceCreator<?>> instanceCreators
      = new HashMap<Type, InstanceCreator<?>>();

  public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) {

    if (typeAdapter instanceof InstanceCreator<?>) {
      //放入map中
      instanceCreators.put(type, (InstanceCreator) typeAdapter);
    }
    //省略部分代码
      return this;
  }

上面代码也很简单就是将type及其对应的InstanceCreator放入一个map中。在构建Gson对象的时候将此map传给了gson对象,详见GsonBuilder的create方法:

  public Gson create() {

    addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, factories);

    //删除与本文无关的代码

    return new Gson(...,..., instanceCreators,
        ..., ...,
        ..., ..., ..., ...,
        ..., ..., ...);
  }

然后进入对应的Gson构造方法:

 private final ConstructorConstructor constructorConstructor;
 Gson(。。。,
      final Map<Type, InstanceCreator<?>> instanceCreators, 。。。。。) {
    this.constructorConstructor = new ConstructorConstructor(instanceCreators);
  }

最总将GsonBuilder的instanceCreators集合转入交给了Gson对象的ConstructorConstructor持有:

public final class ConstructorConstructor {
  private final Map<Type, InstanceCreator<?>> instanceCreators;

  public ConstructorConstructor(Map<Type, InstanceCreator<?>> instanceCreators) {
    this.instanceCreators = instanceCreators;
  }
 }

所以我们在通过ReflectiveTypeAdapterFactory对象初始化TypeAdapter的时候就有了如下这一段:

 public <T> TypeAdapter<T> create(Gson gson, final TypeToken<T> type) {

    //根据type获取ObjectConstructor
    ObjectConstructor<T> constructor = constructorConstructor.get(type);
    return new Adapter<T>(constructor, getBoundFields(gson, type, raw));
  }

需要知道的是ObjectConstructor也是一个接口,其目的是初始化目标javaBean对象:

public interface ObjectConstructor<T> {
  /**
   * Returns a new instance.
   */
  public T construct();
}

那么问题又来了,上面说过InstanceCreator是用来初始化javaBean对象,怎么又冒出来一个ObjectConstructor呢?其实很简单,在ConstructorConstructor的get方法中可以方法下么一段:

  //返回一个ObjectConstructor对象。
  public <T> ObjectConstructor<T> get(TypeToken<T> typeToken) {
    final Type type = typeToken.getType();
    final Class<? super T> rawType = typeToken.getRawType();

    @SuppressWarnings("unchecked") // types must agree
    final InstanceCreator<T> typeCreator = (InstanceCreator<T>) instanceCreators.get(type);
    if (typeCreator != null) {
      return new ObjectConstructor<T>() {
        @Override public T construct() {
          //直接调用typeCreator的createInstance方法
          return typeCreator.createInstance(type);
        }
      };
    }

}

我们知道上文是通过:

//constructor是一个ObjectConstructor对象
T instance = constructor.construct();

来进行JavaBean的初始化的,且通过分析construct()方法就是调用了typeCreator.createInstance() 方法。

其实代码很简单,一步步进入总会了解的,但是只看代码不思考的话并不能学到东西,所以在这里问一个问题:为什么不直接使用InstanceCreator来创建对象,何必多此一举的设计一个ObjectConstructor接口呢?回答这个问题之前
先回答这么一个问题:如果我们没有传InstanceCreator的实现呢,Gson怎么初始化?下面先来回答这个问题,第一个问题就好理解了。

如果没有传InstanceCreator具体实现的话,在这里需要详细的看下ConstructorConstructor的get方法:

public <T> ObjectConstructor<T> get(TypeToken<T> typeToken) {
    final Type type = typeToken.getType();
    final Class<? super T> rawType = typeToken.getRawType();

    // 创建对象方式A
    final InstanceCreator<T> typeCreator = (InstanceCreator<T>) instanceCreators.get(type);
    //客户端没有传InstanceCreator的时候为null
    if (typeCreator != null) {
      return new ObjectConstructor<T>() {//省略部分代码 };
    }

    // 创建对象方式B
    final InstanceCreator<T> rawTypeCreator =
        (InstanceCreator<T>) instanceCreators.get(rawType);
     //客户端没有传InstanceCreator的时候为null   
    if (rawTypeCreator != null) {
      return new ObjectConstructor<T>() {
        @Override public T construct() {//省略部分代码 }
      };
    }

   // 创建对象方式C
    //如果没有配置InstanceCreator的实现
    ObjectConstructor<T> defaultConstructor = newDefaultConstructor(rawType);
    if (defaultConstructor != null) {
      return defaultConstructor;
    }

 // 创建对象方式D

如果没有配置InstanceCreator的实现
 ObjectConstructor<T> defaultImplementation = newDefaultImplementationConstructor(type, rawType);
    if (defaultImplementation != null) {
      return defaultImplementation;
    }

    // finally try unsafe
    return newUnsafeAllocator(type, rawType);
  }

可以发现其实get 方法中有5种策略来初始化一个javaBean对象:
1、根据type通过客户端传入的InstanceCreator
2、根据rawType通过客户端传入的InstanceCreator
3、通过constructor 的newInstance 详见newDefaultConstructor方法
4、判断是否是集合对象,来初始化目标javaBean对象,详见newDefaultImplementationConstructor
5、最后调用newUnsafeAllocator来完成对象的初始化。

如果不设计ObjectConstructor接口的话,那么get方法可能就会被if-elseif -else 这种代码所代替,所以ObjectConstructor在这里其实可以理解为一个策略模式的体现。也可以说是Gson把面向接口或者面向抽象设计耍的很6

所以如果没有传自己的InstanceCreator实现的话,就会默认调用newDefaultConstructor方法来创建一个默认ObjectConstructor方法,该方法其实就是使用了反射来创建对象,其具体实现为:


  private <T> ObjectConstructor<T> newDefaultConstructor(Class<? super T> rawType) {
       //获取构造器对象
      final Constructor<? super T> constructor = rawType.getDeclaredConstructor();
      if (!constructor.isAccessible()) {
        constructor.setAccessible(true);
      }
      return new ObjectConstructor<T>() {

        @Override public T construct() {

            Object[] args = null;
            //调用构造器的的newInstance方法来创建对象
            return (T) constructor.newInstance(args);

        }
      };

  }

一个优秀的框架阅读起来确实让人能体会到不少东西,可惜有的东西是没办法书写出来的,总之慢慢积累吧。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

郭梧悠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值