通过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);
}
};
}
一个优秀的框架阅读起来确实让人能体会到不少东西,可惜有的东西是没办法书写出来的,总之慢慢积累吧。