Mybatis源码解析——反射工具箱

反射工具箱

Reflector

一个Class类对应的Reflector对象包括:

  //对应的Class类型
  private final Class<?> type;
  //可读属性(有get方法的)名字数组
  private final String[] readablePropertyNames;
  //可写属性(有set方法的)名字数组
  private final String[] writeablePropertyNames;
  //set方法,key为属性名称,value是Invoker对象(对set方法对应的method对象的封装)
  private final Map<String, Invoker> setMethods = new HashMap<String, Invoker>();
  //get方法
  private final Map<String, Invoker> getMethods = new HashMap<String, Invoker>();
  //set方法的参数类型
  private final Map<String, Class<?>> setTypes = new HashMap<String, Class<?>>();
  //get方法的返回值类型
  private final Map<String, Class<?>> getTypes = new HashMap<String, Class<?>>();
  //默认构造器
  private Constructor<?> defaultConstructor;
  //所有属性名称,全大写形式
  private Map<String, String> caseInsensitivePropertyMap = new HashMap<String, String>();

以上属性会在构造方法中进行填充

  public Reflector(Class<?> clazz) {
    type = clazz;
    addDefaultConstructor(clazz);
    addGetMethods(clazz);
    addSetMethods(clazz);
    addFields(clazz);//没有set/get方法时会使用Field操作
    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
  private void addGetMethods(Class<?> cls) {
    Map<String, List<Method>> conflictingGetters = new HashMap<String, List<Method>>();
    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)) {
        name = PropertyNamer.methodToProperty(name);
        addMethodConflict(conflictingGetters, name, method);
      }
    }
    resolveGetterConflicts(conflictingGetters);
  }

其流程图如图所示
Mybatis源码解析——反射工具箱_第1张图片

ReflectorFactory

主要提供Reflector对象的创建和缓存,使用concurrentMap缓存对象,key为类

TypeParamterResolver

Type接口的实现类:

  1. Class
  2. ParameterizedType:参数化类型,如List
    • Type getRawType():返回参数化类型中的原始类型;如List返回List
    • Type[] getActualTypeArguments():返回类型变量或实际类型列表,如List返回String
    • Type getOwnerType():返回类型所属关系;如A类的内部类Inner的类型为A
  3. GenericArrayType:数组类型且组成元素是ParameterizedType或TypeVariable;如List[]
    • Type getGenericComponentType():返回数组组成的元素
  4. TypeVariable:类型变量,反应JVM编译该泛型前的信息
    • Type[] getBounds():获取类型变量的上边界,未声明则为Object;如Test中K的上界为Persion
    • D getGenericDeclaration():获取声明该类型变量的原始类型;如Test原始类型为Test
    • String getName():获取在源码中定义时的名字,Test中为K
  5. WildcardType:表示通配符泛型如? super Integer
    • Type[] getUpperBounds():返回范型变量上届
    • Type[] getLowerBounds():返回范型变量下届

ObjectFactory

用来创建对象的工厂,默认实现DefaultObjectFactory其create()调用instantiateClass(),最终调用Constructor.newInstance()

Property工具集

  1. PropertyTokenizer负责解析表达式,可以迭代处理
  2. PropertyNamer负责将方法名转换为属性名(去掉is\set\get等前缀并首字母小写)以及检测是否是set、get方法或属性
  3. PropertyCopier同类型的Bean的属性值拷贝,核心方法为copyBeanProperties()

	
	
result>

分解过程如图所示
Mybatis源码解析——反射工具箱_第2张图片

MetaClass

使用ReflectorPropertyTokenizer组合实现对复杂属性表达式的解析
MetaClass的构造函数接收一个类并为这个类构建Reflector对象
MetaClass.findProperty()会调用buildProperty(),最终通过PropertyTokenizer解析复杂属性表达式
PropertyTokenizer的解析方式见上文,MetaClass.hasGetter()MetaClass.hasSetter()最终都是通过Reflector来实现的

ObjectWrapper

MetaClass是对类级别元信息的封装和处理,ObjectWrapper是对对象的包装,定义了一系列查询对象属性,更新属性的方法


public interface ObjectWrapper {

  Object get(PropertyTokenizer prop);

  void set(PropertyTokenizer prop, Object value);

  String findProperty(String name, boolean useCamelCaseMapping);

  String[] getGetterNames();

  String[] getSetterNames();

  Class<?> getSetterType(String name);

  Class<?> getGetterType(String name);

  boolean hasSetter(String name);

  boolean hasGetter(String name);

  MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory);
  
  boolean isCollection();
  
  void add(Object element);
  
  <E> void addAll(List<E> element);

}

其继承UML图如图所示
Mybatis源码解析——反射工具箱_第3张图片

BaseWrapper是抽象类,封装了MetaObject对象,并提供了三种方法

  • getCollectionValue
  • setCollectionValue
  • resolverCollection:会调用MetaObject.getValue()

getCollectionValue会根据PropertyTokenizer中的index取值


protected Object getCollectionValue(PropertyTokenizer prop, Object collection) {
    if (collection instanceof Map) {
      return ((Map) collection).get(prop.getIndex());
    } else {
      int i = Integer.parseInt(prop.getIndex());
      if (collection instanceof List) {
        return ((List) collection).get(i);
      } else if (collection instanceof Object[]) {
        return ((Object[]) collection)[i];
      } else if (collection instanceof char[]) {
        return ((char[]) collection)[i];
      } else if (collection instanceof boolean[]) {
        return ((boolean[]) collection)[i];
      } else if (collection instanceof byte[]) {
        return ((byte[]) collection)[i];
      } else if (collection instanceof double[]) {
        return ((double[]) collection)[i];
      } else if (collection instanceof float[]) {
        return ((float[]) collection)[i];
      } else if (collection instanceof int[]) {
        return ((int[]) collection)[i];
      } else if (collection instanceof long[]) {
        return ((long[]) collection)[i];
      } else if (collection instanceof short[]) {
        return ((short[]) collection)[i];
      } else {
        throw new ReflectionException("The '" + prop.getName() + "' property of " + collection + " is not a List or Array.");
      }
    }
  }

BeanWrapper针对的是javaBean

  public Object get(PropertyTokenizer prop) {
  //存在索引信息
    if (prop.getIndex() != null) {
    //拿到集合对象
      Object collection = resolveCollection(prop, object);
      //获取对应索引处的值
      return getCollectionValue(prop, collection);
    } else {
    //通过metaClass操作反射get方法
      return getBeanProperty(prop, object);
    }
  }

MetaObject

完成对属性表达式解析的过程,最上层

  //原始JavaBean对象
  private final Object originalObject;
  //JavaBean的ObjectWrapper对象
  private final ObjectWrapper objectWrapper;
  //实例化originalObject的工厂
  private final ObjectFactory objectFactory;
  private final ObjectWrapperFactory objectWrapperFactory;
  private final ReflectorFactory reflectorFactory;

MetaObject的构造方法会根据传入的原始对象类型以及ObjectFactory 的实现创建相应ObjectWrapper 对象
MetaObject和ObjectWrapper中的对类级别的方法如:hasGetter()都是通过MetaClass操作的
对对象级别方法如:getValue是通过与ObjectWrapper配合实现的

关系一览

Mybatis源码解析——反射工具箱_第4张图片

你可能感兴趣的:(mybatis)