Reflector是Mybatis中反射模块的基础,每个Reflector对象都对应一个类,而Reflector中缓存了反射操作需要使用的类的原信息
本片博客详解了下Reflector中各个方法是如何将属性中所需的信息进行填充的,代码中都写入的比较详细的注释
类成员变量解析:
//对应的Class类型
private final Class> type;
//可读属性的名称集合,可读属性就是存在相应get方法的属性
private final String[] readablePropertyNames;
//可写属性的名称集合,可写属性就是存在相应set方法的属性
private final String[] writeablePropertyNames;
//set方法的Map,key是属性的名称,而value则是Invoker对象,是对setter方法对应Method对象的封装
private final Map setMethods = new HashMap();
//get方法的Map,key是属性的名称,而value则是Invoker对象,是对getter方法对应Method对象的封装
private final Map getMethods = new HashMap();
//setter方法中参数值类型的Map,key为属性名称,value为对应的参数类型
private final Map> setTypes = new HashMap();
//getter方法中返回值类型的Map,key为属性名称,value为对应的返回值类型
private final Map> getTypes = new HashMap();
//type指向类型的默认构造函数
private Constructor> defaultConstructor;
//所有属性名称的集合,key为属性名称大写,value为对应的属性名称
private Map caseInsensitivePropertyMap = new HashMap();
构造器解析:
//构造器的参数为Class对象,表明需要封装的类对象
public Reflector(Class> clazz) {
//为type变量赋值
this.type = clazz;
//为defaultConstructor变量赋值
this.addDefaultConstructor(clazz);
//将相应的get方法添加到getMethods中
this.addGetMethods(clazz);
//将相应的set方法添加到setMethods中
this.addSetMethods(clazz);
//将相应setter方法的参数类型添加到setTypes中,将相应的getter方法的返回值类型添加到getTypes中
this.addFields(clazz);
//为readablePropertyNames变量赋值
this.readablePropertyNames = (String[])this.getMethods.keySet().toArray(new String[this.getMethods.keySet().size()]);
//为writeablePropertyNames变量赋值
this.writeablePropertyNames = (String[])this.setMethods.keySet().toArray(new String[this.setMethods.keySet().size()]);
String[] var2 = this.readablePropertyNames;
int var3 = var2.length;
int var4;
String propName;
for(var4 = 0; var4 < var3; ++var4) {
propName = var2[var4];
//将可读属性添加到caseInsensitivePropertyMap中 this.caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
}
var2 = this.writeablePropertyNames;
var3 = var2.length;
for(var4 = 0; var4 < var3; ++var4) {
propName = var2[var4];
//将可写属性添加到caseInsensitivePropertyMap中 this.caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
}
}
获取该类型对应的默认构造器并进行赋值
private void addDefaultConstructor(Class> clazz) {
//获取所有声明的构造器对象
Constructor>[] consts = clazz.getDeclaredConstructors();
Constructor[] var3 = consts;
int var4 = consts.length;
//循环该构造器对象数组
for(int var5 = 0; var5 < var4; ++var5) {
Constructor> constructor = var3[var5];
//判断若该构造器的参数数量为0表示默认构造器
if (constructor.getParameterTypes().length == 0) {
//判断是否可以访问私有方法
if (canAccessPrivateMethods()) {
try {
//若可以的话,设置该方法的访问权限为true
constructor.setAccessible(true);
} catch (Exception var8) {
}
}
if (constructor.isAccessible()) {
this.defaultConstructor = constructor;
}
}
}
}
addGetMethods方法用于向getMethods和getTypes两个属性注入getter方法名称对应Method以及对应返回值类型的Map中
private void addGetMethods(Class> cls) {
Map> conflictingGetters = new HashMap();
//获取该Class对象包含的所有公有方法,包括父类或父接口继承而来的方法(去重)
Method[] methods = this.getClassMethods(cls);
Method[] var4 = methods;
int var5 = methods.length;
//遍历所有方法对应的Method对象
for(int var6 = 0; var6 < var5; ++var6) {
Method method = var4[var6];
//获取属性对应的getter方法应该没有参数类型,这里进行过滤
if (method.getParameterTypes().length <= 0) {
String name = method.getName();
//通过方法名称判断是否为getter方法(按照javabean规范查找getter方法)
//情况一:以get开头,并且名称长度大于3的方法为getter方法
//情况二:以is开头,并且名称长度大于2的方法为getter方法
if (name.startsWith("get") && name.length() > 3 || name.startsWith("is") && name.length() > 2) {
//获取属性名称,即去掉名称开头的get或is,并将首字母小写
name = PropertyNamer.methodToProperty(name);
//将名称和method的映射关系添加到conflictingGetters的Map中
this.addMethodConflict(conflictingGetters, name, method);
}
}
}
//解决冲突并将值添加到相应的getMethods和getTypes中去
this.resolveGetterConflicts(conflictingGetters);
}
private Method[] getClassMethods(Class> cls) {
Map uniqueMethods = new HashMap();
for(Class currentClass = cls; currentClass != null && currentClass != Object.class; currentClass = currentClass.getSuperclass()) {
//getDeclaredMethods方法用于获取Class对象的所有公有的方法,包括从父类或父接口继承而来的方法
//注意和getMethods()方法的区别,该方法只获取Class对象的所有方法,但不包括从父类或父接口继承而来的方法
this.addUniqueMethods(uniqueMethods, currentClass.getDeclaredMethods());
//获取其实现的接口对应的Class对象
Class>[] interfaces = currentClass.getInterfaces();
Class[] var5 = interfaces;
int var6 = interfaces.length;
//遍历接口类型数组,并将其接口的方法添加到Map中
for(int var7 = 0; var7 < var6; ++var7) {
Class> anInterface = var5[var7];
this.addUniqueMethods(uniqueMethods, anInterface.getMethods());
}
}
//获取方法Method对象集合并转化为数组返回
Collection methods = uniqueMethods.values();
return (Method[])methods.toArray(new Method[methods.size()]);
}
private void addUniqueMethods(Map uniqueMethods, Method[] methods) {
Method[] var3 = methods;
int var4 = methods.length;
//遍历Method对象数组
for(int var5 = 0; var5 < var4; ++var5) {
Method currentMethod = var3[var5];
//忽略桥接方法,桥接方法是为了使Java的泛型方法生成的字节码和1.5版本之前的字节码兼容而由编译期自动生成的方法
if (!currentMethod.isBridge()) {
//获取Method对象的标签(返回类型名称+参数名称组合而成的字符串)
String signature = this.getSignature(currentMethod);
if (!uniqueMethods.containsKey(signature)) {
if (canAccessPrivateMethods()) {
try {
currentMethod.setAccessible(true);
} catch (Exception var9) {
}
}
uniqueMethods.put(signature, currentMethod);
}
}
}
}
//判断私有方法是否能够访问
private static boolean canAccessPrivateMethods() {
try {
SecurityManager securityManager = System.getSecurityManager();
if (null != securityManager) {
securityManager.checkPermission(new ReflectPermission("suppressAccessChecks"));
}
return true;
} catch (SecurityException var1) {
return false;
}
}
private String getSignature(Method method) {
StringBuilder sb = new StringBuilder();
Class> returnType = method.getReturnType();
if (returnType != null) {
sb.append(returnType.getName()).append('#');
}
sb.append(method.getName());
Class>[] parameters = method.getParameterTypes();
for(int i = 0; i < parameters.length; ++i) {
if (i == 0) {
sb.append(':');
} else {
sb.append(',');
}
sb.append(parameters[i].getName());
}
return sb.toString();
}
private void addMethodConflict(Map> conflictingMethods, String name, Method method) {
List list = (List)conflictingMethods.get(name);
if (list == null) {
list = new ArrayList();
conflictingMethods.put(name, list);
}
((List)list).add(method);
}
private void resolveGetterConflicts(Map> conflictingGetters) {
//获取Map参数的迭代器
Iterator var2 = conflictingGetters.entrySet().iterator();
while(var2.hasNext()) {
//获取Entry对象
Map.Entry> entry = (Map.Entry)var2.next();
Method winner = null;
//获取属性名称
String propName = (String)entry.getKey();
//获取属性名称对应的getter方法集合,存在集合的原因在于父类中也可能存在同名的getter方法
Iterator var6 = ((List)entry.getValue()).iterator();
//开始循环,最终结果是获取子类的getter方法
while(var6.hasNext()) {
//循环获取getter方法对应的Method对象
Method candidate = (Method)var6.next();
if (winner == null) {
//第一次循环时将Method对象赋值为winner,然后继续循环
winner = candidate;
} else {
//获取前一个Method对象的返回值类型
Class> winnerType = winner.getReturnType();
//获取当前Method对象的返回值类型
Class> candidateType = candidate.getReturnType();
//判断两个getter方法的返回值类型是否相同
if (candidateType.equals(winnerType)) {
//判断当前getter方法的返回值类型是否Boolean类型
if (!Boolean.TYPE.equals(candidateType)) {
throw new ReflectionException("Illegal overloaded getter method with ambiguous type for property " + propName + " in class " + winner.getDeclaringClass() + ". This breaks the JavaBeans specification and can cause unpredictable results.");
}
//判断当前getter方法的名称是否已is开头
if (candidate.getName().startsWith("is")) {
winner = candidate;
}
//判断当前getter方法的返回值类型是否是前一个getter方法的返回值类型的超类或超接口
} else if (!candidateType.isAssignableFrom(winnerType)) {
if (!winnerType.isAssignableFrom(candidateType)) {
throw new ReflectionException("Illegal overloaded getter method with ambiguous type for property " + propName + " in class " + winner.getDeclaringClass() + ". This breaks the JavaBeans specification and can cause unpredictable results.");
}
winner = candidate;
}
}
}
//将该属性对应getter方法以及该方法的返回值类型分别添加到getMethods和getTypes属性中
this.addGetMethod(propName, winner);
}
}
private void addGetMethod(String name, Method method) {
if (this.isValidPropertyName(name)) {
this.getMethods.put(name, new MethodInvoker(method));
//TypeParameterResolver的功能:当存在复杂的继承关系以及泛型定义时,可以帮助解析字段、方法参数或方法返回值的类型
Type returnType = TypeParameterResolver.resolveReturnType(method, this.type);
this.getTypes.put(name, this.typeToClass(returnType));
}
}
private boolean isValidPropertyName(String name) {
//名称不以$符号开头,不等于serialVersionUID,不等于class几位有效属性名
return !name.startsWith("$") && !"serialVersionUID".equals(name) && !"class".equals(name);
}
private Class> typeToClass(Type src) {
Class> result = null;
if (src instanceof Class) {
result = (Class)src;
} else if (src instanceof ParameterizedType) {
result = (Class)((ParameterizedType)src).getRawType();
} else if (src instanceof GenericArrayType) {
Type componentType = ((GenericArrayType)src).getGenericComponentType();
if (componentType instanceof Class) {
result = Array.newInstance((Class)componentType, 0).getClass();
} else {
Class> componentClass = this.typeToClass(componentType);
result = Array.newInstance(componentClass, 0).getClass();
}
}
if (result == null) {
result = Object.class;
}
return result;
}
addSetMethods方法最终用于添加setMethods以及setTypes属性:
private void addSetMethods(Class> cls) {
Map> conflictingSetters = new HashMap();
//获取该Class对象包含的所有公共方法,包括父类或父接口继承而来的方法(去重)
Method[] methods = this.getClassMethods(cls);
Method[] var4 = methods;
int var5 = methods.length;
for(int var6 = 0; var6 < var5; ++var6) {
Method method = var4[var6];
String name = method.getName();
//setter方法都有对应的参数,所有这里没有像getter方法那样判断参数类型为空
if (name.startsWith("set") && name.length() > 3 && method.getParameterTypes().length == 1) {
//获取属性名称,即去掉名称开头的get或is,并将首字母小写
name = PropertyNamer.methodToProperty(name);
//将名称和method的映射关系添加到conflictingGetters的Map中
this.addMethodConflict(conflictingSetters, name, method);
}
}
//解决冲突并将值添加到相应的setMethods和setTypes中去
this.resolveSetterConflicts(conflictingSetters);
}
private void resolveSetterConflicts(Map> conflictingSetters) {
Iterator var2 = conflictingSetters.keySet().iterator();
//遍历参数Map
while(var2.hasNext()) {
//获取key即属性名称
String propName = (String)var2.next();
//获取value及属性名称对应的setter方法集合
List setters = (List)conflictingSetters.get(propName);
//获取属性名称对应的返回值类型
Class> getterType = (Class)this.getTypes.get(propName);
//定义最终匹配的方法
Method match = null;
//定义反射异常
ReflectionException exception = null;
Iterator var8 = setters.iterator();
//开始遍历属性名称对应的setter方法集合
while(var8.hasNext()) {
Method setter = (Method)var8.next();
//获取setter方法的第一个参数类型
Class> paramType = setter.getParameterTypes()[0];
//如果参数类型和该属性对应的getter方法返回类型相同则设置匹配对象为该当前setter方法,然后退出循环
if (paramType.equals(getterType)) {
match = setter;
break;
}
if (exception == null) {
try {
//比较当前setter方法和前一个setter方法,看设置那个setter方法为匹配方法
match = this.pickBetterSetter(match, setter, propName);
} catch (ReflectionException var12) {
match = null;
exception = var12;
}
}
}
if (match == null) {
throw exception;
}
this.addSetMethod(propName, match);
}
}
private Method pickBetterSetter(Method setter1, Method setter2, String property) {
if (setter1 == null) {
//当第一次循环时,前一个setter为空无法比较,直接返回当前setter
return setter2;
} else {
Class> paramType1 = setter1.getParameterTypes()[0];
Class> paramType2 = setter2.getParameterTypes()[0];
//若setter1中参数类型是setter2中参数类型的父类或父接口,返回setter2方法
//即优先获取子类的setter方法
if (paramType1.isAssignableFrom(paramType2)) {
return setter2;
} else if (paramType2.isAssignableFrom(paramType1)) {
return setter1;
} else {
throw new ReflectionException("Ambiguous setters defined for property '" + property + "' in class '" + setter2.getDeclaringClass() + "' with types '" + paramType1.getName() + "' and '" + paramType2.getName() + "'.");
}
}
}
private void addSetMethod(String name, Method method) {
if (this.isValidPropertyName(name)) {
//将setter方法设置到setMethods属性中
this.setMethods.put(name, new MethodInvoker(method));
Type[] paramTypes = TypeParameterResolver.resolveParamTypes(method, this.type);
//将setter方法的参数值类型设置到setTypes属性中去
this.setTypes.put(name, this.typeToClass(paramTypes[0]));
}
}
addField字段也是用于填充setMethods、getMethods、setTypes以及getTypes属性
rivate void addFields(Class> clazz) {
//获取该Class对象所有的公有属性,包括父类或父接口中定义的属性
Field[] fields = clazz.getDeclaredFields();
Field[] var3 = fields;
int var4 = fields.length;
//遍历属性集合
for(int var5 = 0; var5 < var4; ++var5) {
Field field = var3[var5];
if (canAccessPrivateMethods()) {
try {
//设置该属性可编辑修改
field.setAccessible(true);
} catch (Exception var8) {
}
}
if (field.isAccessible()) {
//判断setter方法映射集合中是否包含该属性名
if (!this.setMethods.containsKey(field.getName())) {
int modifiers = field.getModifiers();
//获取该属性的修饰符,并判断该属性不是final或不是类属性
if (!Modifier.isFinal(modifiers) || !Modifier.isStatic(modifiers)) {
this.addSetField(field);
}
}
//判断getter方法映射集合中是否包含该属性名
if (!this.getMethods.containsKey(field.getName())) {
this.addGetField(field);
}
}
}
//如果存在父类,将父类的属性添加进去
if (clazz.getSuperclass() != null) {
this.addFields(clazz.getSuperclass());
}
}
//类似于addSetMethod,这里不再详解
private void addSetField(Field field) {
if (this.isValidPropertyName(field.getName())) {
this.setMethods.put(field.getName(), new SetFieldInvoker(field));
Type fieldType = TypeParameterResolver.resolveFieldType(field, this.type);
this.setTypes.put(field.getName(), this.typeToClass(fieldType));
}
}
//类似于addGetMethod方法,这里不再详解
private void addGetField(Field field) {
if (this.isValidPropertyName(field.getName())) {
this.getMethods.put(field.getName(), new GetFieldInvoker(field));
Type fieldType = TypeParameterResolver.resolveFieldType(field, this.type);
this.getTypes.put(field.getName(), this.typeToClass(fieldType));
}
}