本文参考(精尽 MyBatis 源码分析 —— 反射模块)[http://svip.iocoder.cn/MyBatis/reflection-package/#] 存粹做为一个记录,加深本身的理解。java
mybatis的反射模块,对应reflection包。反射模块做为myabits中的基础支持层,对java原生的反射进行了良好的封装,提供了简洁易用的api,方便上层调用,并对反射操做作了一系列优化,例如缓存了类的元数据,提升了反射操做的性能。apache
今天重点看下Reflector类api
org.apache.ibatis.reflection.Reflector,反射器,每一个Reflector对应一个类。Reflector会缓存反射操做须要的类的信息,例如:构造方法、属性名、setting/getting方法等等。数组
public class Reflector { /** * 对应的类 */ private final Class<?> type; /** * 可读属性数组 */ private final String[] readablePropertyNames; /** * 可写属性数组 */ private final String[] writablePropertyNames; /** * 属性对应的setting方法的映射 * key:属性名称 * value:Invoker对象 */ private final Map<String, Invoker> setMethods = new HashMap<>(); /** * 属性对应的getting方法的映射 * key:属性名称 * value:Invoker对象 */ private final Map<String, Invoker> getMethods = new HashMap<>(); /** * 属性对应的setting方法的方法参数类型的映射 * key:属性名称 * value:方法参数类型 */ private final Map<String, Class<?>> setTypes = new HashMap<>(); /** * 属性对应的getting方法的方法参数类型的映射 * key:属性名称 * value:方法参数类型 */ private final Map<String, Class<?>> getTypes = new HashMap<>(); /** * 默认构造方法 */ private Constructor<?> defaultConstructor; /** * 不区分大小写的属性集合 */ private Map<String, String> caseInsensitivePropertyMap = new HashMap<>(); public Reflector(Class<?> clazz) { // 设置对应的类 type = clazz; // <1> 初始化 defaultConstructor addDefaultConstructor(clazz); // <2> // 初始化 getMethods 和 getTypes ,经过遍历 getting 方法 addGetMethods(clazz); // <3> // 初始化 setMethods 和 setTypes ,经过遍历 setting 方法。 addSetMethods(clazz); // <4> // 初始化 getMethods + getTypes 和 setMethods + setTypes ,经过遍历 fields 属性。 addFields(clazz); // <5> 初始化 readablePropertyNames、writeablePropertyNames、caseInsensitivePropertyMap 属性 readablePropertyNames = getMethods.keySet().toArray(new String[getMethods.keySet().size()]); writeablePropertyNames = setMethods.keySet().toArray(new String[setMethods.keySet().size()]); for (String propName : readablePropertyNames) { caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName); } for (String propName : writeablePropertyNames) { caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName); } }
addGetMethods(Class<?> cls),代码以下:缓存
private void addGetMethods(Class<?> cls) { // <1> 属性与其 getting 方法的映射 Map<String, List<Method>> conflictingGetters = new HashMap<>(); //获取全部方法 Method[] methods = getClassMethods(cls); for (Method method : methods) { //参数大于0,说明不是getting方法,忽略 if (method.getParameterTypes().length > 0) { continue; } //以get或者is开头,说明是getting方法 String name = method.getName(); if ((name.startsWith("get") && name.length() > 3) || (name.startsWith("is") && name.length() > 2)) { //获取属性 name = PropertyNamer.methodToProperty(name); //<2> 添加到conflictingGetters addMethodConflict(conflictingGetters, name, method); } } //解决getting的冲突方法(一个属性,只保留一个对应的方法) resolveGetterConflicts(conflictingGetters); }
private void addMethodConflict(Map<String, List<Method>> conflictingMethods, String name, Method method) { List<Method> list = conflictingMethods.computeIfAbsent(name, k -> new ArrayList<>()); list.add(method); }
接下来,重点看resolveGetterConflicts方法mybatis
private void resolveGetterConflicts(Map<String, List<Method>> conflictingGetters) { // 遍历每一个属性,查找其最匹配的方法。由于子类能够覆写父类的方法,因此一个属性,可能对应多个 getting 方法 for (Entry<String, List<Method>> entry : conflictingGetters.entrySet()) { Method winner = null; // 最匹配的方法 String propName = entry.getKey(); for (Method candidate : entry.getValue()) { // winner 为空,说明 candidate 为最匹配的方法 if (winner == null) { winner = candidate; continue; } // <1> 基于返回类型比较 Class<?> winnerType = winner.getReturnType(); Class<?> candidateType = candidate.getReturnType(); // 类型相同 if (candidateType.equals(winnerType)) { // 返回值类型相同,应该在 getClassMethods 方法中,已经合并。因此抛出 ReflectionException 异常 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."); // 选择 boolean 类型的 is 方法 } else if (candidate.getName().startsWith("is")) { winner = candidate; } // 不符合选择子类 } else if (candidateType.isAssignableFrom(winnerType)) { // OK getter type is descendant // <1.1> 符合选择子类。由于子类能够修改放大返回值。例如,父类的一个方法的返回值为 List ,子类对该方法的返回值能够覆写为 ArrayList 。 } else if (winnerType.isAssignableFrom(candidateType)) { winner = candidate; // <1.2> 返回类型冲突,抛出 ReflectionException 异常 } 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."); } } // <2> 添加到 getMethods 和 getTypes 中 addGetMethod(propName, winner); } }