反射模块

动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。反射的基本术语:Class、Constructor、Field、Method。

一、Reflector和ReflectorFactory

Reflector用于存储类的基本信息,是反射模块的基础,每个Reflector对象都对应一个类,Reflector中缓存反射需要的类的元信息。

  //类的Class类型     
  private Class type;
  //可读属性,存在getter方法的属性
  private String[] readablePropertyNames = EMPTY_STRING_ARRAY;
  //可写属性,存在setter方法的属性
  private String[] writeablePropertyNames = EMPTY_STRING_ARRAY;
  //setter方法,key是属性名,value是Invoker,是对Method的封装
  private Map setMethods = new HashMap();
  //getter方法,key是属性名,value是Invoker,是对Method的封装
  private Map getMethods = new HashMap();
  //属性settter方法的参数值类型,key是属性名,value是参数类型
  private Map> setTypes = new HashMap>();
  //属性getter方法的参数值类型,key是属性名,value是返回值类型
  private Map> getTypes = new HashMap>();
  //无参构造
  private Constructor defaultConstructor;
  //类中所有的属性,key是属性名的大写,value是属性名
  private Map caseInsensitivePropertyMap = new HashMap();

在Reflector的构造方法中初始化上述的字段值。

  public Reflector(Class clazz) {
    type = clazz;
    addDefaultConstructor(clazz);
    //处理clazz的getter方法,填充getMethods集合和getTypes集合
    addGetMethods(clazz);
    //处理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);
    }
  }

举个例子,获取一个简单的JavaBean的Reflector信息。

//price没有对应的getter/setter方法
//存在getBuyTime/setBuyTime方法,但是未显示定义buyTime字段
class Car {
    private String carNo;
    private Integer price;

    public String getCarNo() {
        return carNo;
    }

    public void setCarNo(String carNo) {
        this.carNo = carNo;
    }

    public String getBuyTime() {
        return "2019-11-04";
    }

    public void setBuyTime(String time) {

    }
}

反射模块_第1张图片

ReflectorFactory是创建Reflector的接口,mybatis的唯一实现是DefaultReflectorFactory,可以完成对Reflector的创建和缓存。通过自定义ReflectorFactory实现类完成功能的扩展。

public class DefaultReflectorFactory implements ReflectorFactory {
  //是否允许缓存类的Reflector对象
  private boolean classCacheEnabled = true;
  //使用map进行缓存,key是类的Class类型,vlaue是Reflector对象
  private final ConcurrentMap, Reflector> reflectorMap = new ConcurrentHashMap, 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) {
      //允许使用缓存,先从缓存中查找,没有则新建Reflector对象,然后放入缓存中。
      // 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 {
      //不允许使用缓存,新建reflector对象
      return new Reflector(type);
    }
  }

}

在获取一个类的getter方法时,会获取该类的所有方法再进行过滤,在获取所有方法的过程中会先获取该类的所有方法,为每个方法生成唯一的方法签名,同样会查询该类的所有接口的方法,该类的父类的所有方法。

  private Method[] getClassMethods(Class cls) {
    Map uniqueMethods = new HashMap();
    Class currentClass = cls;
    while (currentClass != null) {
      //为每个公共方法生成唯一的方法签名,uniqueMethods的key就是方法的签名
      //如:java.util.List#getNames
      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 methods = uniqueMethods.values();

    return methods.toArray(new Method[methods.size()]);
  }

reflector.resovleGetterConflicts()方法,用于解决一个属性对应两个方法的问题。比如类SubA继承了A,A中有getNames方法,其返回值为List,SubA重写了getNames方法,返回值为ArrayList,mybatis会为这个属性对应的方法生成不同的签名java.util.List#getNames,java.util.ArrayList#getNames,因为SubA对方法getNames进行了重写,故添加到getMethods中的是SubA中的getNames方法。

二、TypeParameterResolver

当存在复杂的继承关系以及泛型定义时,TypeParameterResolver可以帮助我们解析字段,参数列表、返回值的类型,这是Reflector的基础。

TypeParameterResolver作为类型解析的工具类,所有方法的返回值都是Type类型,因此我们先从Type说起。Type是所有类型的公共接口,Class(实现类),ParameterizedType,GenericArrayType,TypeVariable、WildcardType。

ParameterizedType:泛型类型,如Map,List。getRawType返回原始类型,如List中的List;

getActualTypeArguments获取泛型类型,如String。

TypeVariable:类型变量,如List中的T、T/K/V/E等。getBounds后去类型变量的上边界,未指定则为Object,List则上边界为Person;getGenericDeclaration获取原始类型如List为List;getName返回源码中定义的泛型如List为T。

WildcardType:通配符类型,如List,List。getUpperBounds获取上边界类型,getLowerBounds获取下边界类型。

GenericArrayType:泛型数组类型,元素类型需要是ParameterizedType或TypeVariable,如List[]、T[]、List[]。

getGenericComponentType返回数值元素的类型,如List[]为List即ParameterizedType。

Class:普通类型,除上述之外的类型。

类型存在嵌套。比如:

List外层是ParameterizedType类型,里面又是Class类型。

List外层是ParameterizedType类型,里面是TypeVariable类型。

List[]外层是GenericArrayType类型,里面是ParameterizedType类型,再里面是TypeVariable类型。

List外层是ParameterizedType类型,里面是WildcardType类型。

介绍一种泛型特殊的使用场景:

public class MapperRegistry {

  //泛型没有定义在类型,方法中使用到了泛型T(不管是参数列表还是返回值),因此需要在该方法上
  //定义泛型,若方法中没有使用到泛型,可以不用写
  @SuppressWarnings("unchecked")
  public  T getMapper(Class type, SqlSession sqlSession) {
    final MapperProxyFactory mapperProxyFactory = (MapperProxyFactory) knownMappers.get(type);
    if (mapperProxyFactory == null) {
      throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
    }
    try {
      return mapperProxyFactory.newInstance(sqlSession);
    } catch (Exception e) {
      throw new BindingException("Error getting mapper instance. Cause: " + e, e);
    }
  }

  //Class和Class的区别
  //Class: T类型
  //Class: 通配类型,比如Class[]则数组中的元素可以是任意类型的Class
  //Class[]则数组中的元素可以是T类型的Class
  public void addMappers(String packageName, Class superType) {
    ResolverUtil> resolverUtil = new ResolverUtil>();
    resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
    Set>> mapperSet = resolverUtil.getClasses();
    for (Class mapperClass : mapperSet) {
      addMapper(mapperClass);
    }
  }
}

下面通过一个例子,解析如何在复杂的类继承关系和泛型定义中确认字段的类型,确定泛型的实际类型。

class ClassA {
    protected Map map;
}

class SubClassA extends ClassA {
}

class TestType {
    SubClassA sa = new SubClassA<>();

    public static void main(String[] args) throws NoSuchFieldException {
        //确定map中泛型的具体类型
        Field f = ClassA.class.getDeclaredField("map");
        Type type = TypeParameterResolver.resolveFieldType(f, TestType.class.getDeclaredField("sa").getGenericType());
        System.out.println(type);
    }
}

//打印结果:ParameterizedTypeImpl [rawType=interface java.util.Map, ownerType=null,actualTypeArguments=[class java.lang.Long, class java.lang.Long]]
//这是一个泛型类型,rawType是Map类型,k,v都是Long类型。
  public static Type resolveFieldType(Field field, Type srcType) {
    //获取map的声明类型,Map
    Type fieldType = field.getGenericType();
    //获取map所在类的Class类型,ClassA
    Class declaringClass = field.getDeclaringClass();
    //srcType表示确定K,V类型查找的开始位置。
    return resolveType(fieldType, srcType, declaringClass);
  }
  private static Type resolveType(Type type, Type srcType, Class declaringClass) {
    //根据type的类型选择合适的方法解析
    if (type instanceof TypeVariable) {
      return resolveTypeVar((TypeVariable) type, srcType, declaringClass);
    } else if (type instanceof ParameterizedType) {
      return resolveParameterizedType((ParameterizedType) type, srcType, declaringClass);
    } else if (type instanceof GenericArrayType) {
      return resolveGenericArrayType((GenericArrayType) type, srcType, declaringClass);
    } else {
      return type;
    }
  }
  private static ParameterizedType resolveParameterizedType(ParameterizedType parameterizedType, Type srcType, Class declaringClass) {
    //获取Map的原始类型,Map
    Class rawType = (Class) parameterizedType.getRawType();
    //获取Map的实际类型,K/V
    Type[] typeArgs = parameterizedType.getActualTypeArguments();
    //args是实际确认的类型,此处是Long,Long
    Type[] args = new Type[typeArgs.length];
    for (int i = 0; i < typeArgs.length; i++) {
      if (typeArgs[i] instanceof TypeVariable) {
        //K,V是类型变量,走这个分支
        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];
      }
    }
    //返回ParameterizedTypeResolver的内部类,rawType:Map,args:Long,Long
    return new ParameterizedTypeImpl(rawType, null, args);
  }
  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) {
      //srcType的原始类型是SubClassA
      ParameterizedType parameterizedType = (ParameterizedType) srcType;
      clazz = (Class) parameterizedType.getRawType();
    } else {
      throw new IllegalArgumentException("The 2nd arg must be Class or ParameterizedType, but was: " + srcType.getClass());
    }

    //相等表示需要解析的字段map是在SubClassA中,不使用上述示例
    if (clazz == declaringClass) {
      Type[] bounds = typeVar.getBounds();
      if(bounds.length > 0) {
        return bounds[0];
      }
      return Object.class;
    }

    //获取父类的声明类型,ClassA
    Type superclass = clazz.getGenericSuperclass();
    //递归整个继承结构,完成变量的解析工作
    //类型对应:K,SubClassA,ClassA,SubClassA,ClassA
    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;
      }
    }
    return Object.class;
  }
 //见下图的解析流程  
 private static Type scanSuperTypes(TypeVariable typeVar, Type srcType, Class declaringClass, Class clazz, Type superclass) {
    Type result = null;
    if (superclass instanceof ParameterizedType) {
      ParameterizedType parentAsType = (ParameterizedType) superclass;
      Class parentAsClass = (Class) parentAsType.getRawType();
      if (declaringClass == parentAsClass) {
        Type[] typeArgs = parentAsType.getActualTypeArguments();
        TypeVariable[] declaredTypeVars = declaringClass.getTypeParameters();
        for (int i = 0; i < declaredTypeVars.length; i++) {
          if (declaredTypeVars[i] == typeVar) {
            if (typeArgs[i] instanceof TypeVariable) {
              TypeVariable[] typeParams = clazz.getTypeParameters();
              for (int j = 0; j < typeParams.length; j++) {
                if (typeParams[j] == typeArgs[i]) {
                  if (srcType instanceof ParameterizedType) {
                    result = ((ParameterizedType) srcType).getActualTypeArguments()[j];
                  }
                  break;
                }
              }
            } else {
              result = typeArgs[i];
            }
          }
        }
      } else if (declaringClass.isAssignableFrom(parentAsClass)) {
        result = resolveTypeVar(typeVar, parentAsType, declaringClass);
      }
    } else if (superclass instanceof Class) {
      if (declaringClass.isAssignableFrom((Class) superclass)) {
        result = resolveTypeVar(typeVar, superclass, declaringClass);
      }
    }
    return result;
  }

反射模块_第2张图片

三、ObjectFactory

mybatis中很多地方都会用到ObjectFactory,通过对象工厂可创建指定类型的对象。DefaultObjectFactory是ObjectFactory的唯一实现。通过mybatis-config.xml中的配置可自定义ObjectFactory实现类。

四、Property工具集

PropertyTokenizer:解析mapper文件中的"."和"[]"符号。继承Iterator,可迭代处理。

//以orders[0].id为例,第一次调用PropertyTokenizer的构造方法时
//name:orders
//indexedName:orders[0]
//index:0
//children:id
public class PropertyTokenizer implements Iterator {
  private String name;
  private String indexedName;
  private String index;
  private String children;

  public PropertyTokenizer(String fullname) {
    int delim = fullname.indexOf('.');
    if (delim > -1) {
      name = fullname.substring(0, delim);
      children = fullname.substring(delim + 1);
    } else {
      name = fullname;
      children = null;
    }
    indexedName = name;
    delim = name.indexOf('[');
    if (delim > -1) {
      index = name.substring(delim + 1, name.length() - 1);
      name = name.substring(0, delim);
    }
  }
}

当需要解析的属性很复杂时,需要对PropertyTokenizer进行迭代处理。迭代的效果如下图。

  public PropertyTokenizer next() {
    return new PropertyTokenizer(children);
  }

反射模块_第3张图片

PropertyNamer:主要完成类中方法名到属性名的转换,具体实现主要是将方法中的set/get/is前缀去除。

PropertyCopier:属性拷贝工具类,主要完成相同类型的两个对象的属性拷贝。类似于BeanUtils、BeanCopier。

五、MetaClass

通过Reflector和PropertyTokenizer的组合,完成了对复杂属性表达式的解析。也可判断复杂属性是否有getter/setter方法。假设有一个用户对象User,订单对象Order,一个用户可以持有多个订单。

  //reflectorFactory的缓存中取reflector信息
  private ReflectorFactory reflectorFactory;
  //类的元信息
  private Reflector reflector;

  private MetaClass(Class type, ReflectorFactory reflectorFactory) {
	this.reflectorFactory = reflectorFactory;
    this.reflector = reflectorFactory.findForClass(type);
  }

  public static MetaClass forClass(Class type, ReflectorFactory reflectorFactory) {
    return new MetaClass(type, reflectorFactory);
  }

MetaClass的主要方法有findProperty(name)、hasGetter(name)、hasSetter(name)方法,下面逐一讲解。

findProperty(name):完成复杂属性的验证工作(只查找 . 的导航的属性,不检查下标),如从User实体类中查找order.id属性是否存在,这里并不是直接验证User类中是否有order.id属性,而是先判断User中是否有order属性,再判断Order中是否有id属性。(注:User中持有Order对象)

  //以order.id为例, 验证order.id是否有效,无效返回null,有效返回order.id
  public String findProperty(String name) {
    StringBuilder prop = buildProperty(name, new StringBuilder());
    return prop.length() > 0 ? prop.toString() : null;
  }

  private StringBuilder buildProperty(String name, StringBuilder builder) {
    //属性做分割,name:order,children:id
    PropertyTokenizer prop = new PropertyTokenizer(name);
    if (prop.hasNext()) {
      //从reflector中查找属性,为查到直接结束
      String propertyName = reflector.findPropertyName(prop.getName());
      if (propertyName != null) {
        builder.append(propertyName);
        builder.append(".");
        //查到后获取order对应的类型,Order
        MetaClass metaProp = metaClassForProperty(propertyName);
        //递归查找id属性是否在Order中有效
        metaProp.buildProperty(prop.getChildren(), builder);
      }
    } else {
      //简单属性走这步,这也是递归的出口
      String propertyName = reflector.findPropertyName(name);
      if (propertyName != null) {
        builder.append(propertyName);
      }
    }
    //结果是order.id
    return builder;
  }

  //根据属性的类型,创建对应的MetaClass对象。
  public MetaClass metaClassForProperty(String name) {
    Class propType = reflector.getGetterType(name);
    return MetaClass.forClass(propType, reflectorFactory);
  }

hasGetter(name):判断复杂属性是否存在getter方法,如orders[0].id,先判断User中orders是否有getter方法,再判断Order中id是否有getter方法。

 //以orders[0].id为例
 public boolean hasGetter(String name) {
    //name: orders, indexedName: orders[0], index: 0, children: id
    PropertyTokenizer prop = new PropertyTokenizer(name);
    if (prop.hasNext()) {
      //存在children,判断User的orders属性是否存在
      if (reflector.hasGetter(prop.getName())) {
        //判断orders属性的类型,注意我们这里希望查找到的是Order类型,而不是List类型
        //因为id属性应该是在Order类中的。
        MetaClass metaProp = metaClassForProperty(prop);
        //递归判断children是否有getter方法
        return metaProp.hasGetter(prop.getChildren());
      } else {
        return false;
      }
    } else {
      //递归的出口
      return reflector.hasGetter(prop.getName());
    }
  }

  //获取orders的实际类型,根据此类型创建MetaClass对象。
  private MetaClass metaClassForProperty(PropertyTokenizer prop) {
    Class propType = getGetterType(prop);
    return MetaClass.forClass(propType, reflectorFactory);
  }
  //获取属性的getter方法返回类型  
  private Class getGetterType(PropertyTokenizer prop) {
    //type为集合类型,prop为orders[0]带有索引下标
    Class type = reflector.getGetterType(prop.getName());
    if (prop.getIndex() != null && Collection.class.isAssignableFrom(type)) {
      //获取orders的类型,应该是List
      Type returnType = getGenericGetterType(prop.getName());
      if (returnType instanceof ParameterizedType) {
        //泛型的具体类型Order
        Type[] actualTypeArguments = ((ParameterizedType) returnType).getActualTypeArguments();
        if (actualTypeArguments != null && actualTypeArguments.length == 1) {
          returnType = actualTypeArguments[0];
          if (returnType instanceof Class) {
            type = (Class) returnType;
          } else if (returnType instanceof ParameterizedType) {
            type = (Class) ((ParameterizedType) returnType).getRawType();
          }
        }
      }
    }
    //简单属性,直接返回类型
    return type;
  }


  //如果属性orders有getter方法,TypeParameterResolver从getter方法中获取返回值类型
  //属性无getter方法,TypeParameterResolver从orders字段定义中获取类型
  private Type getGenericGetterType(String propertyName) {
    try {
      Invoker invoker = reflector.getGetInvoker(propertyName);
      if (invoker instanceof MethodInvoker) {
        Field _method = MethodInvoker.class.getDeclaredField("method");
        _method.setAccessible(true);
        Method method = (Method) _method.get(invoker);
        return TypeParameterResolver.resolveReturnType(method, reflector.getType());
      } else if (invoker instanceof GetFieldInvoker) {
        Field _field = GetFieldInvoker.class.getDeclaredField("field");
        _field.setAccessible(true);
        Field field = (Field) _field.get(invoker);
        return TypeParameterResolver.resolveFieldType(field, reflector.getType());
      }
    } catch (NoSuchFieldException e) {
    } catch (IllegalAccessException e) {
    }
    return null;
  }

hasSetter(name):递归判断复杂属性是否有setter方法。

  public boolean hasSetter(String name) {
    PropertyTokenizer prop = new PropertyTokenizer(name);
    if (prop.hasNext()) {
      if (reflector.hasSetter(prop.getName())) {
        MetaClass metaProp = metaClassForProperty(prop.getName());
        return metaProp.hasSetter(prop.getChildren());
      } else {
        return false;
      }
    } else {
      return reflector.hasSetter(prop.getName());
    }
  }

  public MetaClass metaClassForProperty(String name) {
    //直接从reflector中获取属性的类型
    Class propType = reflector.getGetterType(name);
    return MetaClass.forClass(propType, reflectorFactory);
  }

六、ObjectWrapper

通过ObjectWrapperFactory创建ObjectWrapper,ObjectWrapperFactory的实现类DefaultObjectWrapperFactory不可用,需要自己通过mybatis-config.xml扩展自定义的实现类。ObjectWrapper的实现类包含是BaseWrapper(抽象类)、CollectionWrapper。它们是解析复杂属性表达式的最终处理类,提供了set、get等方法。

BaseWrapper是抽象类,封装了MetaObject(解析复杂属性表达式解析类),其实现类包含BeanWrapper、MapWrapper。

BeanWrapper封装了Object object;MapWrapper封装了Map object;CollectionObject封装了Collection object。

复杂属性值的获取最终是从ObjectWrapper封装的对象中拿到的。

七、MetaObject

解析复杂属性表达式解析类,它描述了解析的过程。如orders[0].id; order.id; orders[0]等表达式的解析。在MetaObject中类级别的方法一般是调用MetaClass完成的,对象级别的方法一般配合ObjectWrapper完成。

public class MetaObject {
  //原始javabean对象
  private Object originalObject;
  //objectWrapper对象,封装了originalObject
  private ObjectWrapper objectWrapper;
  //实例化originalObject的工厂类
  private ObjectFactory objectFactory;
  //创建objectWrapper的工厂对象
  private ObjectWrapperFactory objectWrapperFactory;
  //创建并缓存reflector的工厂对象
  private ReflectorFactory reflectorFactory;
}

 

你可能感兴趣的:(Mybatis源码分析)