用了两年多的Spring Data JPA, 再来熟读一下mybatis源码
// 类型
private final Class<?> type;
// getter属性名称集合
private final String[] readablePropertyNames;
// setter属性名称集合
private final String[] writablePropertyNames;
// setter方法集合,key:属性,value: Invoker
private final Map<String, Invoker> setMethods = new HashMap<>();
// getter方法集合,key:属性,value: Invoker
private final Map<String, Invoker> getMethods = new HashMap<>();
// setter属性类型集合,key:属性名称,value:参数类型
private final Map<String, Class<?>> setTypes = new HashMap<>();
// getter属性类型集合,key:属性名称,value:返回值类型
private final Map<String, Class<?>> getTypes = new HashMap<>();
// 无参构造
private Constructor<?> defaultConstructor;
// 属性名称集合, key: 大写属性名,value:属性名称
private Map<String, String> caseInsensitivePropertyMap = new HashMap<>();
Reflector 主要方法就是构造函数 Reflector(Class> clazz),下面是该方法的注释说明
//这个方法主要就是通过映射的方式给参数赋值
public Reflector(Class<?> clazz) {
// 类型
type = clazz;
// 默认无参构造函数赋值
addDefaultConstructor(clazz);
// getMethods,getTypes 赋值, getter方法属性名称以及返回值类型获取保存
addGetMethods(clazz);
// setMethods,setTypes 赋值, setter方法属性名称以及请求参数类型获取保存
addSetMethods(clazz);
// 该对象无getter,setter方法的属性(addGetMethods, addSetMethods 没扫描出来的属性),通过addFields给补上.例如无get,set方法的属性
// setMethods,setTypes,getMethods,getTypes 赋值
addFields(clazz);
// getter属性名称集合
readablePropertyNames = getMethods.keySet().toArray(new String[0]);
// setter属性名称集合
writablePropertyNames = setMethods.keySet().toArray(new String[0]);
// 将属性名称保存到caseInsensitivePropertyMap
for (String propName : readablePropertyNames) {
caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
}
for (String propName : writablePropertyNames) {
caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
}
}
// 默认无参构造函数赋值
private void addDefaultConstructor(Class<?> clazz) {
// 获取该对象所有构造函数
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
// 筛选出无参构造函数并且赋值
Arrays.stream(constructors)
.filter(constructor -> constructor.getParameterTypes().length == 0)// 筛选出无参构造函数
.findAny()// 获取无参构造函数
.ifPresent(constructor -> this.defaultConstructor = constructor);// 给Reflector对象属性defaultConstructor赋值
}
// getMethods,getTypes 赋值, getter方法属性名称以及返回值类型获取保存
private void addGetMethods(Class<?> clazz) {
// 用来装属性集合
Map<String, List<Method>> conflictingGetters = new HashMap<>();
// 获取此类所有的方法
Method[] methods = getClassMethods(clazz);
// 从getter方法中获取属性名称,加入conflictingGetters集合
Arrays.stream(methods)
.filter(m -> m.getParameterTypes().length == 0 && PropertyNamer.isGetter(m.getName())) // 筛选出符合getter的方法
.forEach(m -> addMethodConflict(conflictingGetters, PropertyNamer.methodToProperty(m.getName()), m)); // 加入conflictingGetters集合
//解决getter 方法冲突
resolveGetterConflicts(conflictingGetters);
}
// 获取此类所有的方法
private Method[] getClassMethods(Class<?> clazz) {
// key: 唯一方法key(返回类型#方法名称:参数列表), value:Method
Map<String, Method> uniqueMethods = new HashMap<>();
Class<?> currentClass = clazz;
while (currentClass != null && currentClass != Object.class) {
// getDeclaredMethods 获取此类所有方法
// addUniqueMethods给uniqueMethods赋值
addUniqueMethods(uniqueMethods, currentClass.getDeclaredMethods());
// 获取此类所有接口
Class<?>[] interfaces = currentClass.getInterfaces();
for (Class<?> anInterface : interfaces) {
addUniqueMethods(uniqueMethods, anInterface.getMethods());
}
// 获取此类的父类
currentClass = currentClass.getSuperclass();
}
Collection<Method> methods = uniqueMethods.values();
// 返回获取的所有方法
return methods.toArray(new Method[0]);
}
private void resolveGetterConflicts(Map<String, List<Method>> conflictingGetters) {
// 处理冲突的核心逻辑其实就是比较 getter 方法的返回值,优先选择返回值为子类的 getter 方法
for (Entry<String, List<Method>> entry : conflictingGetters.entrySet()) {
// 属性method
Method winner = null;
// 属性名称
String propName = entry.getKey();
// 是否冲突
boolean isAmbiguous = false;
for (Method candidate : entry.getValue()) {
if (winner == null) {
winner = candidate;
continue;
}
// 两个 Method 使用返回类型做比较
Class<?> winnerType = winner.getReturnType();
Class<?> candidateType = candidate.getReturnType();
if (candidateType.equals(winnerType)) { // 返回类型有冲突
if (!boolean.class.equals(candidateType)) { // 判断返回类型是否是boolean
// 不是boolean 则判断为冲突
isAmbiguous = true;
break;
} else if (candidate.getName().startsWith("is")) { // 为什么是boolean 就不判断为冲突呢?
// 是boolean类型
winner = candidate;
}
} else if (candidateType.isAssignableFrom(winnerType)) {// winnerType 是 candidateType 子类 或 winnerType实现了candidateType接口
// OK getter type is descendant
} else if (winnerType.isAssignableFrom(candidateType)) {// candidateType 是 winnerType 子类 或 candidateType实现了winnerType接口
winner = candidate;
} else {
isAmbiguous = true;
break;
}
}
// 将属性名称加入集合
addGetMethod(propName, winner, isAmbiguous);
}
}
private void addGetMethod(String name, Method method, boolean isAmbiguous) {
MethodInvoker invoker = isAmbiguous
? new AmbiguousMethodInvoker(method, MessageFormat.format(
"Illegal overloaded getter method with ambiguous type for property ''{0}'' in class ''{1}''. This breaks the JavaBeans specification and can cause unpredictable results.",
name, method.getDeclaringClass().getName()))
: new MethodInvoker(method);
getMethods.put(name, invoker);
Type returnType = TypeParameterResolver.resolveReturnType(method, type);
getTypes.put(name, typeToClass(returnType));
}
private void addFields(Class<?> clazz) {
// 获取该类所有字段(不包括父类字段)
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
// 添加 setMethods 集合中不存在的字段
if (!setMethods.containsKey(field.getName())) {
// 获取属性修饰符
int modifiers = field.getModifiers();
// 判断该属性修饰符是否是 final 或 static
if (!(Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers))) {
// 加入setMethods,setTypes集合
addSetField(field);
}
}
// 添加 getMethods 集合中不存在的字段
if (!getMethods.containsKey(field.getName())) {
addGetField(field);
}
}
// 通过递归获取改类以及父类所有属性
if (clazz.getSuperclass() != null) {
addFields(clazz.getSuperclass());
}
}
欢迎补充~
映射大法好!!!