跳至主要內容

MyBatis反射模块分析

IT王小二约 2062 字

MyBatis反射模块分析

作者:IT王小二

博客:https://itwxe.comopen in new window

一、orm查询映射过程

orm查询映射过程

反射是 Mybatis 模块中类最多的模块,通过反射实现了 POJO 对象的实例化和 POJO 的属性赋值,往往提到反射,会想到让性能降低,但是,相对 JDK 自带的反射功能,MyBatis 的反射模块功能更为强大,性能更高(当然还是基于jdk反射的封装)。

反射模块关键的几个类如下:

  • ObjectFactory:MyBatis 每次创建结果对象的新实例时,它都会使用对象工厂(ObjectFactory)去构建 POJO 。
  • ReflectorFactory:创建 Reflector 的工厂类,Reflector 是 MyBatis 反射模块的基础,每个 Reflector 对象都对应一个类,在其中缓存了反射操作所需要的类元信息,提高反射性能的秘密就在这里。
  • ObjectWrapperFactory: ObjectWrapper 的工厂类,用于创建 ObjectWrapper 。
  • ObjectWrapper:对对象的包装,抽象了对象的属性信息,定义了一系列查询对象属性信息的方法,以及更新属性的方法。
  • MetaObject:封装了对象元信息,包装了 MyBatis 中五个核心的反射类。也是提供给外部使用的反射工具类,可以利用它可以读取或者修改对象的属性信息。

二、ObjectFactory

MyBatis 每次创建结果对象的新实例时,它都会使用对象工厂(ObjectFactory)去构建 POJO 。

ObjectFactory

public interface ObjectFactory {

  /**
   * 设置配置信息
   */
  default void setProperties(Properties properties) {
    // NOP
  }

  /**
   * 通过无参构造函数创建指定类的对象
   */
  <T> T create(Class<T> type);

  /**
   * 根据参数列表,选择合适的构造函数创建对象
   */
  <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs);

  /**
   * 检测指定类型是否为集合类型
   */
  <T> boolean isCollection(Class<T> type);

}

ObjectFactory 默认实现类

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);
    // we know types are assignable
    return (T) instantiateClass(classToCreate, constructorArgTypes, constructorArgs);
  }

  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();
        try {
          return constructor.newInstance();
        } catch (IllegalAccessException e) {
          if (Reflector.canControlMemberAccessible()) {
            constructor.setAccessible(true);
            return constructor.newInstance();
          } else {
            throw e;
          }
        }
      }
      // 根据指定的参数列表查找构造函数,并实例化对象
      constructor = type.getDeclaredConstructor(constructorArgTypes.toArray(new Class[0]));
      try {
        return constructor.newInstance(constructorArgs.toArray(new Object[0]));
      } catch (IllegalAccessException e) {
        if (Reflector.canControlMemberAccessible()) {
          constructor.setAccessible(true);
          return constructor.newInstance(constructorArgs.toArray(new Object[0]));
        } else {
          throw e;
        }
      }
    } catch (Exception e) {
      String argTypes = Optional.ofNullable(constructorArgTypes).orElseGet(Collections::emptyList)
          .stream().map(Class::getSimpleName).collect(Collectors.joining(","));
      String argValues = Optional.ofNullable(constructorArgs).orElseGet(Collections::emptyList)
          .stream().map(String::valueOf).collect(Collectors.joining(","));
      throw new ReflectionException("Error instantiating " + type + " with invalid types (" + argTypes + ") or values (" + argValues + "). Cause: " + e, e);
    }
  }

  protected Class<?> resolveInterface(Class<?> type) {
    Class<?> classToCreate;
    if (type == List.class || type == Collection.class || type == Iterable.class) {
      classToCreate = ArrayList.class;
    } else if (type == Map.class) {
      classToCreate = HashMap.class;
    } else if (type == SortedSet.class) { // issue #510 Collections Support
      classToCreate = TreeSet.class;
    } else if (type == Set.class) {
      classToCreate = HashSet.class;
    } else {
      classToCreate = type;
    }
    return classToCreate;
  }

  @Override
  public <T> boolean isCollection(Class<T> type) {
    return Collection.class.isAssignableFrom(type);
  }

}

三、ReflectorFactory

创建 Reflector 的工厂类,Reflector 是 MyBatis 反射模块的基础,每个 Reflector 对象都对应一个类,在其中缓存了反射操作所需要的类元信息,提高反射性能的秘密就在这里。

ReflectorFactory

public interface ReflectorFactory {

  boolean isClassCacheEnabled();

  void setClassCacheEnabled(boolean classCacheEnabled);

  /**
   * 通过class创建Reflector
   */
  Reflector findForClass(Class<?> type);
}

ReflectorFactory 默认实现类: 在 MyBatis 启动加载时就将xml中需要映射的类元信息加载到 reflectorMap 作为缓存,这就是 MyBatis 提升反射性能的密码所在。

public class DefaultReflectorFactory implements ReflectorFactory {
  /**
   * class缓存默认开启
   */
  private boolean classCacheEnabled = true;
  /**
   * 使用ConcurrentMap保证线程安全,以class为key,Reflector为value,保存类元信息
   */
  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
      return reflectorMap.computeIfAbsent(type, Reflector::new);
    } else {
      return new Reflector(type);
    }
  }

}

Reflector:保存类元信息,其中值得注意的是这个类的属性,还有 addFields(Class<?> clazz) 方法,通过 addFields 给这个类添加了get/set方法,哪怕你的pojo不符合规范,没有get/set方法,也给你添加上get/set方法。

public class Reflector {

  /**
   * 对应的class
   */
  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<>();
  /**
   * class默认的构造函数
   */
  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[0]);
    writablePropertyNames = setMethods.keySet().toArray(new String[0]);
    for (String propName : readablePropertyNames) {
      caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
    }
    for (String propName : writablePropertyNames) {
      caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
    }
  }

  /**
   * 给这个类添加了get/set方法,哪怕你的pojo不符合规范,没有get/set方法,也给你添加上get/set方法
   */
  private void addFields(Class<?> clazz) {
    Field[] fields = clazz.getDeclaredFields();
    // 遍历class所有的属性
    for (Field field : fields) {
      // 如果这个属性没有set方法
      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的,那么就给这个属性生成一个Set方法
        if (!(Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers))) {
          addSetField(field);
        }
      }
      // 如果这个属性没有Get方法,那个就给它添加一个Get方法
      if (!getMethods.containsKey(field.getName())) {
        addGetField(field);
      }
    }
    if (clazz.getSuperclass() != null) {
      addFields(clazz.getSuperclass());
    }
  }

  private void addSetField(Field field) {
    if (isValidPropertyName(field.getName())) {
      setMethods.put(field.getName(), new SetFieldInvoker(field));
      Type fieldType = TypeParameterResolver.resolveFieldType(field, type);
      setTypes.put(field.getName(), typeToClass(fieldType));
    }
  }

  private void addGetField(Field field) {
    if (isValidPropertyName(field.getName())) {
      getMethods.put(field.getName(), new GetFieldInvoker(field));
      Type fieldType = TypeParameterResolver.resolveFieldType(field, type);
      getTypes.put(field.getName(), typeToClass(fieldType));
    }
  }
  
  // 省略其他代码
}

四、ObjectWrapperFactory 和 ObjectWrapper

ObjectWrapperFactory:ObjectWrapper 的工厂类,用于创建 ObjectWrapper 。

public interface ObjectWrapperFactory {

  boolean hasWrapperFor(Object object);

  ObjectWrapper getWrapperFor(MetaObject metaObject, Object object);

}

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);

}

看到这个一个接口,那么是怎么实现的呢,来看下它的实现类。

  • public abstract class BaseWrapper implements ObjectWrapper
  • public class BeanWrapper extends BaseWrapper

看下 BeanWrapper 这个类,可以看到这里实现了get/set方法的具体实现,其中有个 metaClass 是什么呢,这个其实就是包装了 ReflectorReflectorFactory

public class BeanWrapper extends BaseWrapper {

  /**
   * 实例对象
   */
  private final Object object;
  /**
   * 元信息
   */
  private final MetaClass metaClass;

  public BeanWrapper(MetaObject metaObject, Object object) {
    super(metaObject);
    this.object = object;
    this.metaClass = MetaClass.forClass(object.getClass(), metaObject.getReflectorFactory());
  }

  @Override
  public Object get(PropertyTokenizer prop) {
    if (prop.getIndex() != null) {
      // 如果是集合属性
      Object collection = resolveCollection(prop, object);
      return getCollectionValue(prop, collection);
    } else {
      // 如果不是集合属性
      return getBeanProperty(prop, object);
    }
  }

  @Override
  public void set(PropertyTokenizer prop, Object value) {
    if (prop.getIndex() != null) {
      // 如果是集合属性
      Object collection = resolveCollection(prop, object);
      setCollectionValue(prop, collection, value);
    } else {
      // 如果不是集合属性
      setBeanProperty(prop, object, value);
    }
  }

  // 省略其他代码
}
public class MetaClass {

  private final ReflectorFactory reflectorFactory;
  private final 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);
  }
 
  // 省略其他代码 
}

五、MetaObject

封装了对象元信息,包装了 MyBatis 中五个核心的反射类。也是提供给外部使用的反射工具类,可以利用它可以读取或者修改对象的属性信息。

public class MetaObject {

  /**
   * 原始的Java对象
   */
  private final Object originalObject;
  private final ObjectWrapper objectWrapper;
  private final ObjectFactory objectFactory;
  private final ObjectWrapperFactory objectWrapperFactory;
  private final ReflectorFactory reflectorFactory;

  // 省略其他代码
}