MyBatis专辑——反射工具类

521 阅读1分钟

在Java中,反射是一种十分强大且灵活的机制,但是其使用门槛相对较高。而Mybatis中就封装了一个反射工具箱,可以更易于使用

反射工具箱的具体实现位于org.apache.ibatis.reflection中。

下面我们来简单解释下其主要构成。

Reflector

Reflector是其中一个很重要的类。这是一个用于缓存类的映射集。

在构造一个Reflector对象时,是通过传入一个Class对象来实现的。

其主要的属性:


  private final Class<?> type;
  private final String[] readablePropertyNames;
  private final String[] writablePropertyNames;
  private final Map<String, Invoker> setMethods = new HashMap<>();
  private final Map<String, Invoker> getMethods = new HashMap<>();
  private final Map<String, Class<?>> setTypes = new HashMap<>();
  private final Map<String, Class<?>> getTypes = new HashMap<>();
  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);
    }
  }

传入一个Class类对象,然后使用type记录该Class的类型。 通过addDefaultConstructor(clazz)方法来初始化默认的构造方法。 addDefaultConstructor()的内部:

private void addDefaultConstructor(Class<?> clazz) {
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
Arrays.stream(constructors).filter(constructor -> constructor.getParameterTypes().length == 0)
  .findAny().ifPresent(constructor -> this.defaultConstructor = constructor);
}

可知,该方法是通过反射获取Class内部的所有构造方法,并遍历,最后过滤出一个无参构造方法,从而初始化defaultConstructor字段。

未完待续