Mybatis基础支持层-反射模块:Reflector/Invoker/ReflectorFactory
Mybatis三层架构:接口层,核心处理层,基础支持层 基础支持层:数据源模块、反射模块、缓存模块、日志模块、事务管理模块、Binding模块、类型转换、资源解析、解析器模块
反射功能非常常见,用于通过类的数据获取对象,或是根据名臣获取对象的属性或方法。org.apache.ibatis.reflection包中,就包含了很多简化反射的API
一、Reflector
- Reflector是mybatis中反射模块的基础
public class Reflector {
//信息对象
private final Class<?> type;
//可以get的属性
private final String[] readablePropertyNames;
//可以set的属性
private final String[] writablePropertyNames;
//记录属性的set方法
private final Map<String, Invoker> setMethods = new HashMap();
//记录属性的get方法
private final Map<String, Invoker> getMethods = new HashMap();
//属性set方法的参数类型
private final Map<String, Class<?>> setTypes = new HashMap();
//属性get方法的参数类型
private final Map<String, Class<?>> getTypes = new HashMap();
//默认构造方法
private Constructor<?> defaultConstructor;
//属性名称的集合
private Map<String, String> caseInsensitivePropertyMap = new HashMap();
...
}
- 在构造方法中初始化以上属性内容
public Reflector(Class<?> clazz) {
type = clazz;
addDefaultConstructor(clazz);
addGetMethods(clazz);
addSetMethods(clazz);
addFields(clazz);
readablePropertyNames = getMethods.keySet().toArray(new String[getMethods.keySet().size()]);
writablePropertyNames = setMethods.keySet().toArray(new String[setMethods.keySet().size()]);
for (String propName : readablePropertyNames) {
caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
}
for (String propName : writablePropertyNames) {
caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
}
}
- 以上就是通过addDefaultConstructor、addGetMethods、addSetMethods、addFields几个方法将参数获取,并初始化
private void addGetMethods(Class<?> cls) {
//conflictingGetters是属性名称,对应getter方法的映射
Map<String, List<Method>> conflictingGetters = new HashMap<>();
//获取所有方法唯一标签和方法的映射
//步骤1: 获取指定类及其父类和接口中定义的方法
Method[] methods = getClassMethods(cls);
for (Method method : methods) {
if (method.getParameterTypes().length > 0) {
continue;
}
String name = method.getName();
if ((name.startsWith("get") && name.length() > 3)
|| (name.startsWith("is") && name.length() > 2)) {
//getter方法,包含普通基础类型和bool类型
name = PropertyNamer.methodToProperty(name);
//把getter方法添加到conflictingGetters集合中
//步骤2:查找getter方法,并添加到conflictingGetters集合中
addMethodConflict(conflictingGetters, name, method);
}
}
//解决子类重写父类方法的场景
//步骤3:方法去重,并将其声明与实现绑定到Reflector对象属性中
resolveGetterConflicts(conflictingGetters);
}
private Method[] getClassMethods(Class<?> cls) {
Map<String, Method> uniqueMethods = new HashMap<>();
Class<?> currentClass = cls;
while (currentClass != null && currentClass != Object.class) {
//每个方法生成一个唯一标签
addUniqueMethods(uniqueMethods, currentClass.getDeclaredMethods());
// we also need to look for interface methods -
// because the class may be abstract
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[methods.size()]);
}
//通过getSignature获取唯一标签
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();
}
- 按照addGetMethods方法的流程:首先获取对应类的方法(含未实现的接口),保存方法的唯一标识和方法的映射,添加到uniqueMethods集合-conflictingGetters集合中,但是如果父类和子类复写方法的场景,产生对应方法的签名是不同的,然后此种情况希望只保留一个实现,那么就会通过resolveGetterConflicts方法,对之前的conflictingGetters集合中的元素进行去重
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()) {
//默认第一个是winner
if (winner == null) {
winner = candidate;
continue;
}
//获取winner的返回值
Class<?> winnerType = winner.getReturnType();
//获取当前对象的返回值
Class<?> candidateType = candidate.getReturnType();
//如果返回值类型,和方法的标识都一致
if (candidateType.equals(winnerType)) {
//不是bool类型
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)) {
//如果winner是当天对象的子类,这是正确的
// OK getter type is descendant
} else if (winnerType.isAssignableFrom(candidateType)) {
//如果当前对象是winner的子类,就需要修改winner对象
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最终将方法及其回调,以及方法返回值的内容保存起来
addGetMethod(propName, winner);
}
}
private void addGetMethod(String name, Method method) {
if (isValidPropertyName(name)) {
//记录方法,绑定回调方法
getMethods.put(name, new MethodInvoker(method));
Type returnType = TypeParameterResolver.resolveReturnType(method, type);
//记录返回值类型
getTypes.put(name, typeToClass(returnType));
}
}
- 读取Class Fields 载对比Setter Getter中是否有遗漏的进行添加
private void addFields(Class<?> clazz) {
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (!setMethods.containsKey(field.getName())) {
// issue #379 - removed the check for final because JDK 1.5 allows
// modification of final fields through reflection (JSR-133). (JGB)
// pr #16 - final static can only be set by the classloader
int modifiers = field.getModifiers();
//过滤掉final和static的方法
if (!(Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers))) {
//补充setter
addSetField(field);
}
}
if (!getMethods.containsKey(field.getName())) {
//补充getter
addGetField(field);
}
}
if (clazz.getSuperclass() != null) {
//处理父类中的属性
addFields(clazz.getSuperclass());
}
}
二、Invoker
通过上面的方法,将属性,及其对应的方法都添加到Reflector的属性中,那下面就来看一下Invoker
-
Invoker接口有三个实现类:GetFieldInvoker,SetFieldInvoker,MethodInvoker
-
GetFieldInvoker,SetFieldInvoker 是通过field字段封装了对应的Field对象,两者的invoke方法是通过Field.get()/set()实现
-
MethodInvoker 通过method字符封装了对应方法,通过Method.invoke实现
//Getter Field
public class GetFieldInvoker implements Invoker {
private final Field field;
public GetFieldInvoker(Field field) {
this.field = field;
}
@Override
public Object invoke(Object target, Object[] args) throws IllegalAccessException {
try {
return field.get(target);
} catch (IllegalAccessException e) {
if (Reflector.canControlMemberAccessible()) {
field.setAccessible(true);
return field.get(target);
} else {
throw e;
}
}
}
@Override
public Class<?> getType() {
return field.getType();
}
}
//Method
public class MethodInvoker implements Invoker {
private final Class<?> type;
private final Method method;
public MethodInvoker(Method method) {
this.method = method;
if (method.getParameterTypes().length == 1) {
type = method.getParameterTypes()[0];
} else {
type = method.getReturnType();
}
}
@Override
public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
try {
return method.invoke(target, args);
} catch (IllegalAccessException e) {
if (Reflector.canControlMemberAccessible()) {
method.setAccessible(true);
return method.invoke(target, args);
} else {
throw e;
}
}
}
@Override
public Class<?> getType() {
return type;
}
}
三、Reflector创建者 ReflectorFactory
public interface ReflectorFactory {
//检测ReflectorFactory 对象能够缓存Reflector
boolean isClassCacheEnabled();
void setClassCacheEnabled(boolean classCacheEnabled);
//获取对应类的Reflector对象
Reflector findForClass(Class<?> type);
}
- mybatis提供的一个默认实现类DefaultReflectorFactory,如果一些定制化的需求,也可自定义来实现对应的工厂
public class DefaultReflectorFactory implements ReflectorFactory {
//能够缓存Reflector对象
private boolean classCacheEnabled = true;
//对应缓存的一个并发Map
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
//如果支持缓存,就从并发map中查看,如果不存在对应key,就新建一个Reflector,以type为参数初始化
//以下是JDK8的写法,旧版就是通过get 并通过Null判断
return reflectorMap.computeIfAbsent(type, Reflector::new);
} else {
//不缓存每次都新建
return new Reflector(type);
}
}
}