一、Reflector
MyBatis在进行参数处理结果集映射等操作时,会涉及大量的反射操作,为了简化反射操作,MyBatis提供了专门的反射模块,该模块位于org.apache.ibatis.reflection包中,它对常见的反射操作做了进一步的封装,提供简单易用的API。
Reflector是MyBatis中反射模块的基础,每一个Reflector对象都对应一个类,在Reflector中缓存了反射操作需要使用的类的元信息。
Reflector中各个字段的含义如下:
//对应的Class类型
private final Class<?> type;
//可读属性的名称集合,可读属性就是存在相应getter方法的属性
private final String[] readablePropertyNames;
//可写属性的名称集合,可写属性就是存在相应setter方法的属性
private final String[] writablePropertyNames;
//记录了属性相应的setter方法,key是属性名称,value是Invoker对象,它是对setter方法对应Method对象的封装。
private final Map<String, Invoker> setMethods = new HashMap<>();
//属性相应的getter方法,key是属性名称,value是Invoker对象。
private final Map<String, Invoker> getMethods = new HashMap<>();
//记录了属性相应的setter方法的参数值类型,key是属性名称,value是setter方法的参数类型。
private final Map<String, Class<?>> setTypes = new HashMap<>();
//记录了属性相应的getter方法的返回值类型,key是属性名称,value是getter方法的参数类型。
private final Map<String, Class<?>> getTypes = new HashMap<>();
//记录默认的构造器
private Constructor<?> defaultConstructor;
//记录所有属性名称的集合
private Map<String, String> caseInsensitivePropertyMap = new HashMap<>();
Reflector的构造器:
public Reflector(Class<?> clazz) {
type = clazz;//初始化type字段
addDefaultConstructor(clazz);//查找clazz的默认构造方法(无参构造器)
addGetMethods(clazz);//初始化getMethods和getTypes集合
addSetMethods(clazz);//初始化setMethods和setTypes集合
addFields(clazz);//处理没有getter/setter方法的字段,获取到的信息会添加到setMethods,getMethods,setTypes ,getTypes
//根据setMethods/getMethods集合初始化可写/读属性的名称集合
readablePropertyNames = getMethods.keySet().toArray(new String[0]);
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);
}
}
Reflector的Reflector.addGetMethods()
由于Reflector.addGetMethods()方法和Reflector.addSetMethods()方法的处理逻辑类似,这里我们只介绍Reflector.addGetMethods()方法。
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()))
.forEach(m -> addMethodConflict(conflictingGetters, PropertyNamer.methodToProperty(m.getName()), m));
//由于存在协变返回类型,例如A类中定义了getNames()方法,返回值类型List<String>,而其子类SubA复写的getNames()方法的返回值类型可以定义为ArrayList<String>。在addUniqueMethods()方法中,这两个方法被当成不同的方法存入uniqueMethods集合中,这显然是不合理的,所以需要调用resolveGetterConflicts()方法处理这种情况,并在resolveGetterConflicts()方法中将其返回值类型填充到getTypes集合。
resolveGetterConflicts(conflictingGetters);
}
/***********获取当前类以及其父类中定义的所有方法的唯一签名以及Method对象*************/
private Method[] getClassMethods(Class<?> clazz) {
//用于记录类中定义的全部方法的唯一签名以及对应的Method对象
Map<String, Method> uniqueMethods = new HashMap<>();
Class<?> currentClass = clazz;
while (currentClass != null && currentClass != Object.class) {
//获取currentClass类中的所有方法
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]);//返回数组
}
/***********为每个方法生成唯一的签名,并记录到uniqueMethods集合中*************/
private void addUniqueMethods(Map<String, Method> uniqueMethods, Method[] methods) {
for (Method currentMethod : methods) {
if (!currentMethod.isBridge()) {
//获取方法签名:返回值类型#方法名称:参数类型列表。方法签名全局唯一。
String signature = getSignature(currentMethod);
//检查在子类中是否已经添加过该方法,如果在子类中已经添加过,则表示子类覆盖了该方法,无需再添加。
if (!uniqueMethods.containsKey(signature)) {
uniqueMethods.put(signature, currentMethod);
}
}
}
}
/************************获取方法签名的方法*******************************/
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++) {
sb.append(i == 0 ? ':' : ',').append(parameters[i].getName());
}
return sb.toString();
}
/**************将方法签名以及其对应的Method对象存入conflictingMethods集合*********************/
private void addMethodConflict(Map<String, List<Method>> conflictingMethods, String name, Method method) {
List<Method> list = conflictingMethods.computeIfAbsent(name, k -> new ArrayList<>());
list.add(method);
}
/**************处理协变类型返回值,同时填充getTypes集合*********************/
private void resolveGetterConflicts(Map<String, List<Method>> conflictingGetters) {
for (Entry<String, List<Method>> entry : conflictingGetters.entrySet()) {
Method winner = null;
String propName = entry.getKey();
for (Method candidate : entry.getValue()) {
if (winner == null) {
winner = candidate;
continue;
}
Class<?> winnerType = winner.getReturnType();
Class<?> candidateType = candidate.getReturnType();
if (candidateType.equals(winnerType)) {
if (!boolean.class.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.");
} else if (candidate.getName().startsWith("is")) {
winner = candidate;
}
} else if (candidateType.isAssignableFrom(winnerType)) {
// OK getter type is descendant
} else if (winnerType.isAssignableFrom(candidateType)) {
winner = candidate;
} else {
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.");
}
}
addGetMethod(propName, winner);
}
}
private void addGetMethod(String name, Method method) {
if (isValidPropertyName(name)) {
getMethods.put(name, new MethodInvoker(method));//添加Invoker
Type returnType = TypeParameterResolver.resolveReturnType(method, type);
getTypes.put(name, typeToClass(returnType));
}
}
二、ReflectorFactory
该接口主要实现了对Reflector对象的创建和缓存:
package org.apache.ibatis.reflection;
public interface ReflectorFactory {
boolean isClassCacheEnabled();//检测ReflectorFactory对象是否会缓存Reflector对象
void setClassCacheEnabled(boolean classCacheEnabled);//设置是否缓存Reflector对象
Reflector findForClass(Class<?> type);//创建指定Class对应的Reflector对象
}
该接口的默认实现类:
package org.apache.ibatis.reflection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public class DefaultReflectorFactory implements ReflectorFactory {
private boolean classCacheEnabled = true;
private final ConcurrentMap<Class<?>, Reflector> reflectorMap = new ConcurrentHashMap<>();//缓存
public DefaultReflectorFactory() {
}
@Override
public boolean isClassCacheEnabled() {
return classCacheEnabled;
}
@Override
public void setClassCacheEnabled(boolean classCacheEnabled) {
this.classCacheEnabled = classCacheEnabled;
}
@Override
public Reflector findForClass(Class<?> type) {
if (classCacheEnabled) {
// synchronized (type) removed see issue #461
return reflectorMap.computeIfAbsent(type, Reflector::new);
} else {
return new Reflector(type);
}
}
}
我们可以在配置文件中自定义自己的ReflectorFactory实现,从而扩展功能。