2.2、mybatis源码分析--基础模块之reflect反射工具集

  反射是mybatis框架的基础,也是java开发框架的比用知识。在mybatis中提供了反射工具集来帮助mybatis完成参数转换、类型转换、参数填充、方法调用、动态代理等等功能。

一、Reflector类

  • Reflector是mybatis反射模块的基础,每一个Reflector对象对应一个类,在Reflector中缓存了反射操作需要使用的类的元信息
    定义的属性
public class Reflector {
 //是否缓存
  private static boolean classCacheEnabled = true;
  //空数组
  private static final String[] EMPTY_STRING_ARRAY = new String[0];
  //用于存放类型--反射类对应的map
  private static final Map<Class<?>, Reflector> REFLECTOR_MAP = new ConcurrentHashMap<Class<?>, Reflector>();
    //对象class类型
  private Class<?> type;
  //存在相应的getter方法的属性
  private String[] readablePropertyNames = EMPTY_STRING_ARRAY;
  //存在相应setter方法的属性
  private String[] writeablePropertyNames = EMPTY_STRING_ARRAY;
  //记录属性相应的setter方法,key为属性名称,value为invoker对象
  private Map<String, Invoker> setMethods = new HashMap<String, Invoker>();
  //记录相应getter方法的集合
  private Map<String, Invoker> getMethods = new HashMap<String, Invoker>();
  //记录相应setter方法的参数值类型,value是setter方法的参数类型
  private Map<String, Class<?>> setTypes = new HashMap<String, Class<?>>();
  private Map<String, Class<?>> getTypes = new HashMap<String, Class<?>>();
  //默认构造方法
  private Constructor<?> defaultConstructor;
    //记录所有属性名称的集合
  private Map<String, String> caseInsensitivePropertyMap = new HashMap<String, String>();

构造函数,对上述属性进行填充

//解析指定的class对象,并填充上面的集合
private Reflector(Class<?> clazz) {
    type = clazz;
    //查找clazz的默认构造方法
    addDefaultConstructor(clazz);
    //处理getter方法并填充getMethods和getTypes集合
    addGetMethods(clazz);
    //处理setter方法并填充setMethods和setTypes集合
    addSetMethods(clazz);
    //处理没有getter和setter方法的字段
    addFields(clazz);
    //根据getMethods、setMethods集合,初始化可读可写属性的集合
    readablePropertyNames = getMethods.keySet().toArray(new String[getMethods.keySet().size()]);
    writeablePropertyNames = setMethods.keySet().toArray(new String[setMethods.keySet().size()]);
    //初始化caseInsensitivePropertyMap集合,记录所有大写格式的属性名称
    for (String propName : readablePropertyNames) {
      caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
    }
    for (String propName : writeablePropertyNames) {
      caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
    }
  }

重点方法讲解

1.处理getter方法并填充getMethods和getTypes集合
private void addGetMethods(Class<?> cls) {
    Map<String, List<Method>> conflictingGetters = new HashMap<String, List<Method>>();
    Method[] methods = getClassMethods(cls);
    //遍历并找出相应的get方法
    for (Method method : methods) {
      String name = method.getName();
      if (name.startsWith("get") && name.length() > 3) {
        if (method.getParameterTypes().length == 0) {
          name = PropertyNamer.methodToProperty(name);
          addMethodConflict(conflictingGetters, name, method);
        }
      } else if (name.startsWith("is") && name.length() > 2) {
        if (method.getParameterTypes().length == 0) {
          name = PropertyNamer.methodToProperty(name);
          addMethodConflict(conflictingGetters, name, method);
        }
      }
    }
    //解决子类和父类方法覆盖时候同时存在的冲突
    resolveGetterConflicts(conflictingGetters);
  }
2.获取当前类及其父类中定义的所有方法的唯一签名及相应的Method对象
private Method[] getClassMethods(Class<?> cls) {
    HashMap<String, Method> uniqueMethods = new HashMap<String, Method>();
    Class<?> currentClass = cls;
    while (currentClass != null) {
    //记录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();
    //返回method数组
    return methods.toArray(new Method[methods.size()]);
  }
3.为每一个方法生成唯一签名并记录到uniqueMethods集合中
private void addUniqueMethods(HashMap<String, Method> uniqueMethods, Method[] methods) {
    for (Method currentMethod : methods) {
      if (!currentMethod.isBridge()) {
      //返回值类型#方法名:参数类型列表(是唯一的可以作为唯一标识)
        String signature = getSignature(currentMethod);
        //是否已近添加
        if (!uniqueMethods.containsKey(signature)) {
          if (canAccessPrivateMethods()) {
            try {
              currentMethod.setAccessible(true);
            } catch (Exception e) {
              // Ignored. This is only a final precaution, nothing we can do.
            }
          }

          uniqueMethods.put(signature, currentMethod);
        }
      }
    }
  }
4.获取方法签名(唯一标签)
 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();
  }
5.解决子类和父类方法覆盖时候同时存在的冲突
 private void resolveGetterConflicts(Map<String, List<Method>> conflictingGetters) {
    for (String propName : conflictingGetters.keySet()) {
      List<Method> getters = conflictingGetters.get(propName);
      Iterator<Method> iterator = getters.iterator();
      Method firstMethod = iterator.next();
      if (getters.size() == 1) {
        //如果只有一个说明不存在冲突可以直接添加
        addGetMethod(propName, firstMethod);
      } else {
      //不只有一个,需要比较getter方法的返回值,选择getter方法迭代过程中的临时变量,用于记录迭代到目前为止,最适合的getter方法发
        Method getter = firstMethod;
        //记录返回值类型
        Class<?> getterType = firstMethod.getReturnType();
        while (iterator.hasNext()) {
          Method method = iterator.next();
          Class<?> methodType = method.getReturnType();//获取返回值类型
          if (methodType.equals(getterType)) {//前面应该过滤的
            throw new ReflectionException("Illegal overloaded getter method with ambiguous type for property " 
                + propName + " in class " + firstMethod.getDeclaringClass()
                + ".  This breaks the JavaBeans " + "specification and can cause unpredicatble results.");
         //methodType是getterType的父类或者父接口或者两个相同
          } else if (methodType.isAssignableFrom(getterType)) {
            // 当前最合适的方法的返回值就是当前方法返回值额子类
            
          } else if (getterType.isAssignableFrom(methodType)) {
            getter = method;
            getterType = methodType;
          } else {
            throw new ReflectionException("Illegal overloaded getter method with ambiguous type for property " 
                + propName + " in class " + firstMethod.getDeclaringClass()
                + ".  This breaks the JavaBeans " + "specification and can cause unpredicatble results.");
          }
        }
        addGetMethod(propName, getter);
      }
    }
  }
6.完成方法的填充
  private void addGetMethod(String name, Method method) {
    if (isValidPropertyName(name)) {
    //统一封装成invoker对象
      getMethods.put(name, new MethodInvoker(method));
      getTypes.put(name, method.getReturnType());
    }
  }
7.验证属性是否合法
    private boolean isValidPropertyName(String name) {
    return !(name.startsWith("$") || "serialVersionUID".equals(name) || "class".equals(name));
  }
....其他方法类似

二、Invoker接口

  • 完成Reflector初始化时候封装add*Method等方法在向上述集合添加元素的时候会将相应的getter/setter方法对应的method及字段对应的field对象统一封装成invoker对象
public interface Invoker {
//调用获取指定字段的值后,执行指定的方法
  Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException;
  Class<?> getType();
}
  • Invoker接口有三个实现类,分别是MethodInvoker、GetFieldInvoker、SetFieldInvoker

三、ReflectorFactory接口

  • 实现了对Reflector对象的创建和缓存
public interface ReflectorFactory {
//检测该ReflectorFactory是否缓存了Reflector
  boolean isClassCacheEnabled();
//设置缓存
  void setClassCacheEnabled(boolean classCacheEnabled);
//创建指定class对应的reflector对象
  Reflector findForClass(Class<?> type);
}
  • 实现类,DefaultReflectorFactory
public class DefaultReflectorFactory implements ReflectorFactory {
//是否缓存
  private boolean classCacheEnabled = true;
//使用map按类型存Reflector
  private final ConcurrentMap<Class<?>, Reflector> reflectorMap = new ConcurrentHashMap<Class<?>, Reflector>();
  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
      Reflector cached = reflectorMap.get(type);
      if (cached == null) {
        cached = new Reflector(type);
        reflectorMap.put(type, cached);
      }
      return cached;
    } else {
      return new Reflector(type);
    }
  }
}

四、TypeParameterResolver

  • 是一个工具类,提供了一些列静态方法来解析指定类中的字段、方法返回值或者方法参数类型,TypeParameterResolver中各个静态方法之间的调用关系大致如图:


    调用关系图

1.Type接口

jdk提供的顶级接口,表示的是所有类型的父接口

  • Type接口的子类描述
(1)Class类(比较熟悉就不过多介绍)
(2)ParameterizedType(参数化类型)
public interface ParameterizedType extends Type {
//返回参数化原始类型比如List<String>
    Type[] getActualTypeArguments();
    //获取参数化类型的类型变量或者实际类型的列表
    Type getRawType();
    //返回类型所属的类型
    Type getOwnerType();
}
(3)TypeVariable(类型变量,反应在jvm编译该泛型前的信息)
//例如List<T>中的T就是类型变量, 它在编译时候需要被转为一个具体的类型后才能使用
public interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement {
    //获取类型变量的上边界,如果未明确声明上边界则默认Object,例如<K extends Person>那么上边界就是Person
    Type[] getBounds();
    //获取声明该类型变量的原始类型,<K extends Person>原始类型就是K
    D getGenericDeclaration();
    //获取源码中定义时候的名字
    String getName();
    //java8新增
     AnnotatedType[] getAnnotatedBounds();
}
(4)GenericArrayType
//表示的是数组类型且组成元素是TypeVariable或者ParameterizedType
public interface GenericArrayType extends Type {
//返回数组的组成元素
    Type getGenericComponentType();
}
(5)WildcardType
//表示统配符号泛型例如? extends Number
public interface WildcardType extends Type {
//返回泛型变量的上界
    Type[] getUpperBounds();
    //返回泛型变量的下界
    Type[] getLowerBounds();
}

2、TypeParameterResolver工具类

  • TypeParameterResolver通过resoveFieldType()方法、resolveReturnType()方法和resolveParamTypes()方法分别解析字段类型、方法返回值类型和方法参数列表中各个参数的类型。这三个方法的逻辑基本类似,这里以resolveFieldType为例子来进行介绍。
1.resoveFieldType方法
public static Type resolveFieldType(Field field, Type srcType) {
    Type fieldType = field.getGenericType();//获取字段的声明类型
    Class<?> declaringClass = field.getDeclaringClass();//获取字段定义所在类的Class对象
    return resolveType(fieldType, srcType, declaringClass);
  }
2.根据type类型(字段、方法参数、方法返回值)选择合适的方法进行解析,srcType表示查找该字段、返
回值或者方法参数的起始位置,declaringClass表示该字段、方法定义所在的类
   private static Type resolveType(Type type, Type srcType, Class<?> declaringClass) {
    if (type instanceof TypeVariable) {//解析TypeVariable类型
      return resolveTypeVar((TypeVariable<?>) type, srcType, declaringClass);
    } else if (type instanceof ParameterizedType) {//解析ParameterizedType类型
      return resolveParameterizedType((ParameterizedType) type, srcType, declaringClass);
    } else if (type instanceof GenericArrayType) {//解析GenericArrayType类型
      return resolveGenericArrayType((GenericArrayType) type, srcType, declaringClass);
    } else {
      return type;//class类型
    }
  }
2.1resolveTypeVar负责解析TypeVariable,例如解析map字段的K和V
   private static Type resolveTypeVar(TypeVariable<?> typeVar, Type srcType, Class<?> declaringClass) {
    Type result = null;
    Class<?> clazz = null;
    if (srcType instanceof Class) {
      clazz = (Class<?>) srcType;
    } else if (srcType instanceof ParameterizedType) {
      ParameterizedType parameterizedType = (ParameterizedType) srcType;
      clazz = (Class<?>) parameterizedType.getRawType();
    } else {
      throw new IllegalArgumentException("The 2nd arg must be Class or ParameterizedType, but was: " + srcType.getClass());
    }

    if (clazz == declaringClass) {
      Type[] bounds = typeVar.getBounds();//获取上界
      if(bounds.length > 0) {
        return bounds[0];
      }
      return Object.class;
    }
//获取父类
    Type superclass = clazz.getGenericSuperclass();
    //递归扫面父类进行解析
    result = scanSuperTypes(typeVar, srcType, declaringClass, clazz, superclass);
    if (result != null) {
      return result;
    }

    Type[] superInterfaces = clazz.getGenericInterfaces();
    for (Type superInterface : superInterfaces) {
      result = scanSuperTypes(typeVar, srcType, declaringClass, clazz, superInterface);
      if (result != null) {
        return result;
      }
    }
    //如果整个继承结构中没有解析成功,返回Object
    return Object.class;
  }
2.2解析参数化类型
private static ParameterizedType resolveParameterizedType(ParameterizedType parameterizedType, Type srcType, Class<?> declaringClass) {
   //获取原始类型对象的Class对象,例如public Map<K, V> map;对应的Class对象
    Class<?> rawType = (Class<?>) parameterizedType.getRawType();
    //类型变量K, V值
    Type[] typeArgs = parameterizedType.getActualTypeArguments();
    //用于保存解析后的结果
    Type[] args = new Type[typeArgs.length];
    for (int i = 0; i < typeArgs.length; i++) {
      if (typeArgs[i] instanceof TypeVariable) {//解析变量类型
        args[i] = resolveTypeVar((TypeVariable<?>) typeArgs[i], srcType, declaringClass);
      } else if (typeArgs[i] instanceof ParameterizedType) {
        args[i] = resolveParameterizedType((ParameterizedType) typeArgs[i], srcType, declaringClass);
      } else if (typeArgs[i] instanceof WildcardType) {
        args[i] = resolveWildcardType((WildcardType) typeArgs[i], srcType, declaringClass);
      } else {
        args[i] = typeArgs[i];
      }
    }
    //封装成ParameterizedType并返回,例子中的args为string
    return new ParameterizedTypeImpl(rawType, null, args);
  }

五、ObjectFactory接口

  • 该接口提供了许多个create()方法的重载,通过这些create()方法可以创建指定类型的对象
public interface ObjectFactory {
  void setProperties(Properties properties);//设置配置信息
  <T> T create(Class<T> type);//通过无参数构造器创建指定类的对象
  //根据参数列表,从指定类型中选择合适的构造器创建对象
  <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs);
  //判断是否是集合类
  <T> boolean isCollection(Class<T> type);
}
  • 唯一实现类DefaultObjectFactory

是一个反射工厂,其中create方法通过instantiateClass方法实现,instantiateClass会根据传入的参数列表选择合适的构造函数实例化对象

public class DefaultObjectFactory implements ObjectFactory, Serializable {
  private static final long serialVersionUID = -8855120656740914948L;
  @Override
  public <T> T create(Class<T> type) {
    return create(type, null, null);
  }
  @SuppressWarnings("unchecked")
  @Override
  public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
    Class<?> classToCreate = resolveInterface(type);
    return (T) instantiateClass(classToCreate, constructorArgTypes, constructorArgs);
  }
  @Override
  public void setProperties(Properties properties) {
    // no props for default
  }
  private  <T> T instantiateClass(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
    try {
      Constructor<T> constructor;
      //创建对象
      if (constructorArgTypes == null || constructorArgs == null) {
        constructor = type.getDeclaredConstructor();
        if (!constructor.isAccessible()) {
          constructor.setAccessible(true);
        }
        return constructor.newInstance();
      }
      //根据指定的参数列表查找构造函数,并实例化对象
      constructor = type.getDeclaredConstructor(constructorArgTypes.toArray(new Class[constructorArgTypes.size()]));
      if (!constructor.isAccessible()) {
        constructor.setAccessible(true);
      }
      return constructor.newInstance(constructorArgs.toArray(new Object[constructorArgs.size()]));
    } catch (Exception e) {
      StringBuilder argTypes = new StringBuilder();
      if (constructorArgTypes != null && !constructorArgTypes.isEmpty()) {
        for (Class<?> argType : constructorArgTypes) {
          argTypes.append(argType.getSimpleName());
          argTypes.append(",");
        }
        argTypes.deleteCharAt(argTypes.length() - 1); // remove trailing ,
      }
      StringBuilder argValues = new StringBuilder();
      if (constructorArgs != null && !constructorArgs.isEmpty()) {
        for (Object argValue : constructorArgs) {
          argValues.append(String.valueOf(argValue));
          argValues.append(",");
        }
        argValues.deleteCharAt(argValues.length() - 1); // remove trailing ,
      }
      throw new ReflectionException("Error instantiating " + type + " with invalid types (" + argTypes + ") or values (" + argValues + "). Cause: " + e, e);
    }
  }
....
}
  • 同时提供了在config文件中指定自定义的ObjectFactory接口实现类,扩展功能

六、MetaClass

  • MetaClass通过Reflector和PropertyTokenizer组合使用,实现了对复杂的属性表达式的解析并实现了获取指定属性描述信息的功能

源码解读待定...

七、ObjectWrapper

  • 对类级别的元信息的封装和处理,通过对对象的包装,抽象了对象的属性信息,定义了一系列查询对象属性信息的方法,以及更新属性的方法

源码解读待定...

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342