码字不易,请大佬们点点关注,谢谢~
一、ReflectiveTypeAdapterFactory概述
1.1 在Gson中的核心地位
ReflectiveTypeAdapterFactory是Gson库中处理Java对象序列化和反序列化的核心工厂类。它通过Java反射机制,动态分析Java类的字段结构,并基于这些信息创建对应的TypeAdapter,从而实现Java对象与JSON数据之间的自动转换。
在Gson的默认配置中,大部分普通Java对象的序列化和反序列化都是通过ReflectiveTypeAdapterFactory创建的适配器来完成的。因此,深入理解ReflectiveTypeAdapterFactory的工作原理,对于掌握Gson的核心机制至关重要。
1.2 反射式类型适配的优势与局限
反射式类型适配的主要优势在于:
- 自动化:无需为每个Java类编写显式的序列化和反序列化代码,Gson会自动处理大多数情况。
- 灵活性:支持嵌套对象、集合和数组等复杂数据结构。
- 易用性:对于简单的Java Bean,只需少量配置甚至无需配置即可使用。
然而,反射式类型适配也存在一些局限性:
- 性能开销:反射操作比直接代码执行慢,尤其是在处理大量对象时。
- 访问限制:需要正确设置字段的可访问性,可能受到Java访问修饰符的限制。
- 安全性问题:在某些环境下(如Android的ProGuard混淆),反射可能会受到影响。
1.3 与其他TypeAdapterFactory的关系
Gson通过TypeAdapterFactory链来处理不同类型的序列化和反序列化。ReflectiveTypeAdapterFactory是这个链中的重要一环,通常作为最后一个工厂被调用,用于处理那些没有被其他工厂处理的类型。
Gson的默认工厂链顺序大致如下:
- 处理@JsonAdapter注解的工厂
- 基本类型(如int、String)的工厂
- 集合和数组的工厂
- 反射式工厂(ReflectiveTypeAdapterFactory)
当需要序列化或反序列化某个类型时,Gson会按顺序遍历工厂链,直到找到一个能够处理该类型的工厂。如果所有工厂都无法处理,则会抛出异常。
二、ReflectiveTypeAdapterFactory的核心结构
2.1 类定义与主要成员变量
ReflectiveTypeAdapterFactory的类定义如下:
public final class ReflectiveTypeAdapterFactory implements TypeAdapterFactory {
private final ConstructorConstructor constructorConstructor; // 用于创建对象的构造器
private final FieldNamingStrategy fieldNamingPolicy; // 字段命名策略
private final Excluder excluder; // 字段排除器
private final JsonAdapterAnnotationTypeAdapterFactory jsonAdapterFactory; // 处理@JsonAdapter注解的工厂
// 内部类:用于表示Java类的字段及其绑定信息
static abstract class BoundField {
final String name; // JSON字段名
final boolean serialized; // 是否序列化
final boolean deserialized; // 是否反序列化
protected BoundField(String name, boolean serialized, boolean deserialized) {
this.name = name;
this.serialized = serialized;
this.deserialized = deserialized;
}
// 序列化时写入字段值
abstract void write(JsonWriter writer, Object value) throws IOException, IllegalAccessException;
// 反序列化时读取字段值
abstract void read(JsonReader reader, Object value) throws IOException, IllegalAccessException;
// 判断字段是否可空
abstract boolean writeField(Object value) throws IOException, IllegalAccessException;
}
// 构造函数
public ReflectiveTypeAdapterFactory(
ConstructorConstructor constructorConstructor,
FieldNamingStrategy fieldNamingPolicy,
Excluder excluder,
JsonAdapterAnnotationTypeAdapterFactory jsonAdapterFactory) {
this.constructorConstructor = constructorConstructor;
this.fieldNamingPolicy = fieldNamingPolicy;
this.excluder = excluder;
this.jsonAdapterFactory = jsonAdapterFactory;
}
// 实现TypeAdapterFactory接口的方法,创建TypeAdapter
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
Class<? super T> raw = type.getRawType();
// 检查是否为接口或抽象类
if (!Object.class.isAssignableFrom(raw)) {
return null; // 只能处理Object的子类
}
// 检查是否有@JsonAdapter注解
JsonAdapter annotation = type.getRawType().getAnnotation(JsonAdapter.class);
if (annotation != null) {
// 如果有@JsonAdapter注解,委托给jsonAdapterFactory处理
return jsonAdapterFactory.create(gson, type, annotation);
}
// 创建并返回反射式TypeAdapter
return new Adapter<>(
constructorConstructor.get(type),
getBoundFields(gson, type, raw)
);
}
// 内部类:反射式TypeAdapter的实现
static final class Adapter<T> extends TypeAdapter<T> {
private final ObjectConstructor<T> constructor; // 对象构造器
private final Map<String, BoundField> boundFields; // 绑定的字段
Adapter(ObjectConstructor<T> constructor, Map<String, BoundField> boundFields) {
this.constructor = constructor;
this.boundFields = boundFields;
}
// 序列化方法
@Override
public void write(JsonWriter out, T value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
out.beginObject();
try {
for (BoundField boundField : boundFields.values()) {
if (boundField.writeField(value)) {
out.name(boundField.name);
boundField.write(out, value);
}
}
} catch (IllegalAccessException e) {
throw new AssertionError(e);
}
out.endObject();
}
// 反序列化方法
@Override
public T read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
// 创建实例
T instance = constructor.construct();
try {
in.beginObject();
while (in.hasNext()) {
// 读取JSON字段名
String name = in.nextName();
// 查找匹配的BoundField
BoundField field = boundFields.get(name);
if (field == null || !field.deserialized) {
// 如果没有找到匹配的字段或字段不可反序列化,则跳过
in.skipValue();
} else {
// 读取字段值
field.read(in, instance);
}
}
in.endObject();
} catch (IllegalStateException e) {
throw new JsonSyntaxException(e);
} catch (IllegalAccessException e) {
throw new AssertionError(e);
}
return instance;
}
}
// 获取绑定字段的方法
private Map<String, BoundField> getBoundFields(
Gson context, TypeToken<?> type, Class<?> raw) {
// 实现逻辑...
}
}
2.2 关键组件解析
2.2.1 ConstructorConstructor
ConstructorConstructor是一个工厂类,用于创建对象的构造器。它提供了多种方式来实例化对象,包括:
- 使用无参构造函数
- 使用默认构造函数
- 使用Unsafe.allocateInstance(在无构造函数可用时)
- 使用自定义的实例创建策略
public final class ConstructorConstructor {
private final Map<Type, InstanceCreator<?>> instanceCreators;
// 获取对象构造器
public <T> ObjectConstructor<T> get(TypeToken<T> typeToken) {
final Type type = typeToken.getType();
final Class<? super T> rawType = typeToken.getRawType();
// 尝试使用InstanceCreator
InstanceCreator<T> creator = (InstanceCreator<T>) instanceCreators.get(type);
if (creator != null) {
return new ObjectConstructor<T>() {
@Override
public T construct() {
return creator.createInstance(type);
}
};
}
// 尝试使用针对原始类型的构造器
creator = (InstanceCreator<T>) instanceCreators.get(rawType);
if (creator != null) {
return new ObjectConstructor<T>() {
@Override
public T construct() {
return creator.createInstance(type);
}
};
}
// 尝试创建无参构造函数的构造器
ObjectConstructor<T> defaultConstructor = newDefaultConstructor(rawType);
if (defaultConstructor != null) {
return defaultConstructor;
}
// 尝试创建默认构造函数的构造器
ObjectConstructor<T> defaultImplementation = newDefaultImplementationConstructor(type, rawType);
if (defaultImplementation != null) {
return defaultImplementation;
}
// 使用Unsafe.allocateInstance
return newUnsafeAllocator(type, rawType);
}
// 其他方法...
}
2.2.2 FieldNamingStrategy
FieldNamingStrategy是一个接口,用于定义Java字段名到JSON字段名的映射策略。Gson提供了多种内置实现:
public interface FieldNamingStrategy {
// 将Java字段转换为JSON字段名
public String translateName(Field f);
}
// 内置实现示例
public enum FieldNamingPolicy implements FieldNamingStrategy {
// 使用原始字段名
IDENTITY {
@Override public String translateName(Field f) {
return f.getName();
}
},
// 将字段名转换为小写,并用下划线分隔
LOWER_CASE_WITH_UNDERSCORES {
@Override public String translateName(Field f) {
return lowerCaseWithUnderscores(f.getName());
}
private String lowerCaseWithUnderscores(String s) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (Character.isUpperCase(c)) {
if (i > 0) {
result.append('_');
}
result.append(Character.toLowerCase(c));
} else {
result.append(c);
}
}
return result.toString();
}
},
// 其他策略...
}
2.2.3 Excluder
Excluder是一个用于排除字段的组件,它根据各种规则决定哪些字段应该被序列化或反序列化。
public final class Excluder implements ExclusionStrategy, Cloneable {
private double version = -1; // 版本号
private int modifiers = Modifier.TRANSIENT | Modifier.STATIC; // 要排除的修饰符
private boolean serializeInnerClasses = true; // 是否序列化内部类
private boolean requireExpose; // 是否需要@Expose注解
private final List<ExclusionStrategy> serializationStrategies = new ArrayList<>(); // 序列化排除策略
private final List<ExclusionStrategy> deserializationStrategies = new ArrayList<>(); // 反序列化排除策略
// 检查字段是否应该被排除
@Override
public boolean excludeField(Field field, boolean serialize) {
// 检查字段修饰符
if ((field.getModifiers() & modifiers) != 0) {
return true;
}
// 检查是否为内部类
if (!serializeInnerClasses && isInnerClass(field.getType())) {
return true;
}
// 检查是否为匿名类或本地类
if (isAnonymousOrLocal(field.getType())) {
return true;
}
// 检查版本控制注解
if (version != -1) {
Since since = field.getAnnotation(Since.class);
if (since != null && since.value() > version) {
return true;
}
Until until = field.getAnnotation(Until.class);
if (until != null && until.value() <= version) {
return true;
}
}
// 检查@Expose注解
if (requireExpose) {
Expose expose = field.getAnnotation(Expose.class);
if (expose == null) {
return true;
}
if (serialize ? !expose.serialize() : !expose.deserialize()) {
return true;
}
}
// 应用注册的排除策略
List<ExclusionStrategy> list = serialize
? serializationStrategies
: deserializationStrategies;
for (ExclusionStrategy exclusionStrategy : list) {
if (exclusionStrategy.shouldSkipField(fieldAttributes(field))) {
return true;
}
}
return false;
}
// 其他方法...
}
三、反射式类型适配的工作流程
3.1 适配器的创建过程
当Gson需要序列化或反序列化某个类型时,会调用ReflectiveTypeAdapterFactory的create方法来尝试创建适配器:
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
Class<? super T> raw = type.getRawType();
// 检查是否为接口或抽象类
if (!Object.class.isAssignableFrom(raw)) {
return null; // 只能处理Object的子类
}
// 检查是否有@JsonAdapter注解
JsonAdapter annotation = type.getRawType().getAnnotation(JsonAdapter.class);
if (annotation != null) {
// 如果有@JsonAdapter注解,委托给jsonAdapterFactory处理
return jsonAdapterFactory.create(gson, type, annotation);
}
// 创建并返回反射式TypeAdapter
return new Adapter<>(
constructorConstructor.get(type),
getBoundFields(gson, type, raw)
);
}
3.2 字段绑定过程
getBoundFields方法是ReflectiveTypeAdapterFactory的核心方法之一,它负责收集类的所有字段并创建对应的BoundField:
private Map<String, BoundField> getBoundFields(
Gson context, TypeToken<?> type, Class<?> raw) {
Map<String, BoundField> result = new LinkedHashMap<>();
if (raw.isInterface()) {
return result; // 接口没有字段
}
Type declaredType = type.getType();
while (raw != Object.class) {
// 获取类的所有字段
Field[] fields = raw.getDeclaredFields();
for (Field field : fields) {
// 检查字段是否应该被排除
boolean serialize = !excludeField(field, true);
boolean deserialize = !excludeField(field, false);
if (!serialize && !deserialize) {
continue; // 如果既不序列化也不反序列化,则跳过
}
// 设置字段可访问
field.setAccessible(true);
// 获取字段的泛型类型
Type fieldType = $Gson$Types.resolve(type.getType(), raw, field.getGenericType());
// 获取字段的JSON名称
List<String> fieldNames = getFieldNames(field);
// 为字段创建BoundField
BoundField boundField = createBoundField(
context, field, fieldNames,
TypeToken.get(fieldType),
serialize,
deserialize
);
// 将BoundField添加到结果中
for (String name : fieldNames) {
BoundField previous = result.put(name, boundField);
if (previous != null) {
throw new IllegalArgumentException(
"Duplicate field name '" + name + "'. Found on " +
previous.field + " and " + field);
}
}
}
// 处理父类字段
type = TypeToken.get($Gson$Types.resolve(type.getType(), raw, raw.getGenericSuperclass()));
raw = type.getRawType();
}
return result;
}
3.3 序列化过程
当需要将Java对象序列化为JSON时,ReflectiveTypeAdapterFactory创建的适配器会执行以下步骤:
@Override
public void write(JsonWriter out, T value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
out.beginObject(); // 开始写入JSON对象
try {
// 遍历所有绑定的字段
for (BoundField boundField : boundFields.values()) {
if (boundField.writeField(value)) {
// 写入字段名
out.name(boundField.name);
// 写入字段值
boundField.write(out, value);
}
}
} catch (IllegalAccessException e) {
throw new AssertionError(e);
}
out.endObject(); // 结束写入JSON对象
}
3.4 反序列化过程
当需要将JSON数据反序列化为Java对象时,适配器会执行以下步骤:
@Override
public T read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
// 创建实例
T instance = constructor.construct();
try {
in.beginObject(); // 开始读取JSON对象
while (in.hasNext()) {
// 读取JSON字段名
String name = in.nextName();
// 查找匹配的BoundField
BoundField field = boundFields.get(name);
if (field == null || !field.deserialized) {
// 如果没有找到匹配的字段或字段不可反序列化,则跳过
in.skipValue();
} else {
// 读取字段值
field.read(in, instance);
}
}
in.endObject(); // 结束读取JSON对象
} catch (IllegalStateException e) {
throw new JsonSyntaxException(e);
} catch (IllegalAccessException e) {
throw new AssertionError(e);
}
return instance;
}
四、SerializedName注解的处理
4.1 注解解析过程
ReflectiveTypeAdapterFactory在处理字段时,会检查字段上是否存在@SerializedName注解,并根据注解的值确定JSON字段名:
// 获取字段的JSON名称
private List<String> getFieldNames(Field field) {
SerializedName annotation = field.getAnnotation(SerializedName.class);
if (annotation == null) {
// 如果没有注解,使用字段命名策略转换的名称
return Collections.singletonList(fieldNamingPolicy.translateName(field));
}
// 获取主名称
String serializedName = annotation.value();
// 获取备选名称
String[] alternates = annotation.alternate();
// 构建名称列表(主名称在前,备选名称在后)
List<String> fieldNames = new ArrayList<>(1 + alternates.length);
fieldNames.add(serializedName);
Collections.addAll(fieldNames, alternates);
return fieldNames;
}
4.2 备选名称的处理
@SerializedName注解的alternate属性允许指定多个备选名称。在反序列化时,Gson会尝试所有可能的名称来匹配JSON字段:
// 将所有名称(主名称和备选名称)都映射到同一个BoundField
for (String name : fieldNames) {
BoundField previous = result.put(name, boundField);
if (previous != null) {
throw new IllegalArgumentException(
"Duplicate field name '" + name + "'. Found on " +
previous.field + " and " + field);
}
}
五、性能优化与挑战
5.1 反射性能开销
反射式类型适配的主要性能开销来自以下几个方面:
- 字段查找:通过反射获取类的字段信息需要消耗一定时间。
- 访问权限设置:设置字段的可访问性(
setAccessible(true))也有一定开销。 - 字段值读写:通过反射读写字段值比直接访问慢。
5.2 性能优化策略
Gson采取了多种策略来优化反射性能:
-
缓存反射结果:ReflectiveTypeAdapterFactory在初始化时一次性获取所有字段信息,并创建对应的BoundField,后续操作直接使用缓存结果。
-
预生成适配器:在某些情况下,Gson可以预生成反射代码,避免运行时反射。
-
使用Unsafe:在无构造函数可用时,使用
sun.misc.Unsafe.allocateInstance创建对象,避免调用构造函数的开销。
5.3 与直接编码的性能对比
与手动编写的序列化和反序列化代码相比,反射式类型适配通常会慢一些。但在大多数情况下,这种性能差异并不显著,除非是在性能敏感的场景下(如处理大量数据)。
以下是一个简单的性能测试对比(数据仅作示例,实际结果可能因环境而异):
| 操作类型 | 反射式适配 (ms) | 手动编码 (ms) | 性能差异 |
|---|---|---|---|
| 序列化 10000 个对象 | 85 | 52 | ~63% |
| 反序列化 10000 个对象 | 92 | 61 | ~51% |
六、高级应用与扩展
6.1 自定义FieldNamingStrategy
通过实现FieldNamingStrategy接口,可以自定义Java字段名到JSON字段名的映射规则。例如:
public class CustomFieldNamingStrategy implements FieldNamingStrategy {
@Override
public String translateName(Field field) {
// 将Java字段名转换为大写
return field.getName().toUpperCase();
}
}
// 使用自定义命名策略
Gson gson = new GsonBuilder()
.setFieldNamingStrategy(new CustomFieldNamingStrategy())
.create();
6.2 自定义ExclusionStrategy
通过实现ExclusionStrategy接口,可以自定义字段排除规则。例如:
public class CustomExclusionStrategy implements ExclusionStrategy {
@Override
public boolean shouldSkipField(FieldAttributes f) {
// 排除所有以"secret"开头的字段
return f.getName().startsWith("secret");
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
// 不排除任何类
return false;
}
}
// 使用自定义排除策略
Gson gson = new GsonBuilder()
.addSerializationExclusionStrategy(new CustomExclusionStrategy())
.addDeserializationExclusionStrategy(new CustomExclusionStrategy())
.create();
6.3 与其他TypeAdapterFactory结合
ReflectiveTypeAdapterFactory可以与其他TypeAdapterFactory结合使用,以处理特殊类型或场景。例如:
// 创建自定义工厂
class CustomTypeAdapterFactory implements TypeAdapterFactory {
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
if (type.getRawType() == MySpecialType.class) {
return (TypeAdapter<T>) new MySpecialTypeAdapter();
}
return null;
}
}
// 注册自定义工厂
Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(new CustomTypeAdapterFactory())
.create();
在这个例子中,CustomTypeAdapterFactory会优先处理MySpecialType类型,而其他类型仍由ReflectiveTypeAdapterFactory处理。
七、总结与展望
7.1 ReflectiveTypeAdapterFactory的优势
ReflectiveTypeAdapterFactory作为Gson的核心组件,具有以下优势:
- 自动化:无需为每个Java类编写显式的序列化和反序列化代码,大大简化了开发流程。
- 灵活性:通过注解和策略接口,可以灵活配置序列化和反序列化行为。
- 广泛适用性:能够处理大多数普通Java对象,包括嵌套结构和集合。
- 可扩展性:可以通过自定义FieldNamingStrategy、ExclusionStrategy等进行扩展。
7.2 未来发展方向
随着Java和Android技术的发展,ReflectiveTypeAdapterFactory可能会在以下方向发展:
- 编译时处理:引入编译时注解处理,在编译期生成反射代码,进一步提高性能。
- Kotlin支持:更好地支持Kotlin语言特性,如数据类、协程等。
- 多平台支持:在Kotlin Multiplatform项目中提供更好的支持,实现跨平台的数据转换。
- 性能优化:继续优化反射性能,减少反射开销。
- 简化API:提供更简洁的API,降低开发者使用门槛。
通过不断优化和扩展,ReflectiveTypeAdapterFactory将继续作为Gson的核心组件,为开发者提供高效、灵活的Java对象与JSON数据之间的转换解决方案。