Mybatis基础支持层-反射模块-01

Reflector/Invoker/ReflectorFactory

Posted by Claire on June 13, 2020

Mybatis基础支持层-反射模块:Reflector/Invoker/ReflectorFactory

Mybatis三层架构:接口层,核心处理层,基础支持层 基础支持层:数据源模块、反射模块、缓存模块、日志模块、事务管理模块、Binding模块、类型转换、资源解析、解析器模块

反射功能非常常见,用于通过类的数据获取对象,或是根据名臣获取对象的属性或方法。org.apache.ibatis.reflection包中,就包含了很多简化反射的API

一、Reflector

  • Reflector是mybatis中反射模块的基础
public class Reflector {
    //信息对象
    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();
    //默认构造方法
    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[getMethods.keySet().size()]);
    writablePropertyNames = setMethods.keySet().toArray(new String[setMethods.keySet().size()]);
    for (String propName : readablePropertyNames) {
      caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
    }
    for (String propName : writablePropertyNames) {
      caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
    }
  }

  • 以上就是通过addDefaultConstructor、addGetMethods、addSetMethods、addFields几个方法将参数获取,并初始化
 private void addGetMethods(Class<?> cls) {
     //conflictingGetters是属性名称,对应getter方法的映射
     Map<String, List<Method>> conflictingGetters = new HashMap<>();
         //获取所有方法唯一标签和方法的映射
         //步骤1: 获取指定类及其父类和接口中定义的方法
    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)) {
              //getter方法,包含普通基础类型和bool类型
        name = PropertyNamer.methodToProperty(name);
        //把getter方法添加到conflictingGetters集合中
        //步骤2:查找getter方法,并添加到conflictingGetters集合中
        addMethodConflict(conflictingGetters, name, method);
      }
    }
    //解决子类重写父类方法的场景
    //步骤3:方法去重,并将其声明与实现绑定到Reflector对象属性中
    resolveGetterConflicts(conflictingGetters);
    }

  private Method[] getClassMethods(Class<?> cls) {
    Map<String, Method> uniqueMethods = new HashMap<>();
    Class<?> currentClass = cls;
    while (currentClass != null && currentClass != Object.class) {
        //每个方法生成一个唯一标签
      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<Method> methods = uniqueMethods.values();

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

  //通过getSignature获取唯一标签
   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();
  }


  • 按照addGetMethods方法的流程:首先获取对应类的方法(含未实现的接口),保存方法的唯一标识和方法的映射,添加到uniqueMethods集合-conflictingGetters集合中,但是如果父类和子类复写方法的场景,产生对应方法的签名是不同的,然后此种情况希望只保留一个实现,那么就会通过resolveGetterConflicts方法,对之前的conflictingGetters集合中的元素进行去重
private void resolveGetterConflicts(Map<String, List<Method>> conflictingGetters) {
    for (Entry<String, List<Method>> entry : conflictingGetters.entrySet()) {
      Method winner = null;
      //获取对应方法唯一标识
      String propName = entry.getKey();
      //遍历对应方法的列表
      for (Method candidate : entry.getValue()) {
          //默认第一个是winner
        if (winner == null) {
          winner = candidate;
          continue;
        }
        //获取winner的返回值
        Class<?> winnerType = winner.getReturnType();
        //获取当前对象的返回值
        Class<?> candidateType = candidate.getReturnType();
        //如果返回值类型,和方法的标识都一致
        if (candidateType.equals(winnerType)) {
            //不是bool类型
          if (!boolean.class.equals(candidateType)) {
              //不应该出现,完全相同的方法前面的步骤就应该过滤
            throw new ReflectionException(
                "Illegal overloaded getter method with ambiguous type for property "
                    + propName + " in class " + winner.getDeclaringClass()
                    + ". This breaks the JavaBeans specification and can cause unpredictable results.");
          } else if (candidate.getName().startsWith("is")) {
            winner = candidate;
          }
        } else if (candidateType.isAssignableFrom(winnerType)) {
            //如果winner是当天对象的子类,这是正确的
          // OK getter type is descendant
        } else if (winnerType.isAssignableFrom(candidateType)) {
            //如果当前对象是winner的子类,就需要修改winner对象
          winner = candidate;
        } else {
          throw new ReflectionException(
              "Illegal overloaded getter method with ambiguous type for property "
                  + propName + " in class " + winner.getDeclaringClass()
                  + ". This breaks the JavaBeans specification and can cause unpredictable results.");
        }
      }
      //通过addGetMethod最终将方法及其回调,以及方法返回值的内容保存起来
      addGetMethod(propName, winner);
    }
  }

   private void addGetMethod(String name, Method method) {
    if (isValidPropertyName(name)) {
        //记录方法,绑定回调方法
      getMethods.put(name, new MethodInvoker(method));
      Type returnType = TypeParameterResolver.resolveReturnType(method, type);
      //记录返回值类型
      getTypes.put(name, typeToClass(returnType));
    }
  }
  • 读取Class Fields 载对比Setter Getter中是否有遗漏的进行添加
private void addFields(Class<?> clazz) {
    Field[] fields = clazz.getDeclaredFields();
    for (Field field : fields) {
      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的方法
        if (!(Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers))) {
            //补充setter
          addSetField(field);
        }
      }
      if (!getMethods.containsKey(field.getName())) {
          //补充getter
        addGetField(field);
      }
    }
    if (clazz.getSuperclass() != null) {
        //处理父类中的属性
      addFields(clazz.getSuperclass());
    }
  }

二、Invoker

通过上面的方法,将属性,及其对应的方法都添加到Reflector的属性中,那下面就来看一下Invoker

  • Invoker接口有三个实现类:GetFieldInvoker,SetFieldInvoker,MethodInvoker

  • GetFieldInvoker,SetFieldInvoker 是通过field字段封装了对应的Field对象,两者的invoke方法是通过Field.get()/set()实现

  • MethodInvoker 通过method字符封装了对应方法,通过Method.invoke实现

//Getter Field
public class GetFieldInvoker implements Invoker {
  private final Field field;

  public GetFieldInvoker(Field field) {
    this.field = field;
  }

  @Override
  public Object invoke(Object target, Object[] args) throws IllegalAccessException {
    try {
      return field.get(target);
    } catch (IllegalAccessException e) {
      if (Reflector.canControlMemberAccessible()) {
        field.setAccessible(true);
        return field.get(target);
      } else {
        throw e;
      }
    }
  }

  @Override
  public Class<?> getType() {
    return field.getType();
  }
}

//Method
public class MethodInvoker implements Invoker {

  private final Class<?> type;
  private final Method method;

  public MethodInvoker(Method method) {
    this.method = method;

    if (method.getParameterTypes().length == 1) {
      type = method.getParameterTypes()[0];
    } else {
      type = method.getReturnType();
    }
  }

  @Override
  public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
    try {
      return method.invoke(target, args);
    } catch (IllegalAccessException e) {
      if (Reflector.canControlMemberAccessible()) {
        method.setAccessible(true);
        return method.invoke(target, args);
      } else {
        throw e;
      }
    }
  }

  @Override
  public Class<?> getType() {
    return type;
  }
}

三、Reflector创建者 ReflectorFactory

public interface ReflectorFactory {
 //检测ReflectorFactory 对象能够缓存Reflector
  boolean isClassCacheEnabled();

  void setClassCacheEnabled(boolean classCacheEnabled);
//获取对应类的Reflector对象
  Reflector findForClass(Class<?> type);
}
  • mybatis提供的一个默认实现类DefaultReflectorFactory,如果一些定制化的需求,也可自定义来实现对应的工厂
public class DefaultReflectorFactory implements ReflectorFactory {
    //能够缓存Reflector对象
  private boolean classCacheEnabled = true;
  //对应缓存的一个并发Map
  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
      //如果支持缓存,就从并发map中查看,如果不存在对应key,就新建一个Reflector,以type为参数初始化
      //以下是JDK8的写法,旧版就是通过get 并通过Null判断
      return reflectorMap.computeIfAbsent(type, Reflector::new);
    } else {
        //不缓存每次都新建
      return new Reflector(type);
    }
  }

}