MyBatis构架设计学习------反射工具箱------Reflector&ReflectorFactory

一、Reflector

MyBatis在进行参数处理结果集映射等操作时,会涉及大量的反射操作,为了简化反射操作,MyBatis提供了专门的反射模块,该模块位于org.apache.ibatis.reflection包中,它对常见的反射操作做了进一步的封装,提供简单易用的API。
Reflector是MyBatis中反射模块的基础,每一个Reflector对象都对应一个类,在Reflector中缓存了反射操作需要使用的类的元信息。
Reflector中各个字段的含义如下:

 //对应的Class类型
 private final Class<?> type;
 //可读属性的名称集合,可读属性就是存在相应getter方法的属性
  private final String[] readablePropertyNames;
  //可写属性的名称集合,可写属性就是存在相应setter方法的属性
  private final String[] writablePropertyNames;
  //记录了属性相应的setter方法,key是属性名称,value是Invoker对象,它是对setter方法对应Method对象的封装。
  private final Map<String, Invoker> setMethods = new HashMap<>();
  //属性相应的getter方法,key是属性名称,value是Invoker对象。
  private final Map<String, Invoker> getMethods = new HashMap<>();
  //记录了属性相应的setter方法的参数值类型,key是属性名称,value是setter方法的参数类型。
  private final Map<String, Class<?>> setTypes = new HashMap<>();
  //记录了属性相应的getter方法的返回值类型,key是属性名称,value是getter方法的参数类型。
  private final Map<String, Class<?>> getTypes = new HashMap<>();
  //记录默认的构造器
  private Constructor<?> defaultConstructor;
  //记录所有属性名称的集合
  private Map<String, String> caseInsensitivePropertyMap = new HashMap<>();

Reflector的构造器:

public Reflector(Class<?> clazz) {
    type = clazz;//初始化type字段
    addDefaultConstructor(clazz);//查找clazz的默认构造方法(无参构造器)
    addGetMethods(clazz);//初始化getMethods和getTypes集合
    addSetMethods(clazz);//初始化setMethods和setTypes集合
    addFields(clazz);//处理没有getter/setter方法的字段,获取到的信息会添加到setMethods,getMethods,setTypes ,getTypes 
    //根据setMethods/getMethods集合初始化可写/读属性的名称集合
    readablePropertyNames = getMethods.keySet().toArray(new String[0]);
    writablePropertyNames = setMethods.keySet().toArray(new String[0]);
    //初始化caseInsensitivePropertyMap集合,其中记录的属性名称全部是大写
    for (String propName : readablePropertyNames) {
      caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
    }
    for (String propName : writablePropertyNames) {
      caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
    }
  }

Reflector的Reflector.addGetMethods()
由于Reflector.addGetMethods()方法和Reflector.addSetMethods()方法的处理逻辑类似,这里我们只介绍Reflector.addGetMethods()方法。

 private void addGetMethods(Class<?> clazz) {
    Map<String, List<Method>> conflictingGetters = new HashMap<>();
    Method[] methods = getClassMethods(clazz);//获取当前类的所有方法
    //判断是否是getter方法,并存入conflictingGetters集合中
    Arrays.stream(methods).filter(m -> m.getParameterTypes().length == 0 && PropertyNamer.isGetter(m.getName()))
      .forEach(m -> addMethodConflict(conflictingGetters, PropertyNamer.methodToProperty(m.getName()), m));
    //由于存在协变返回类型,例如A类中定义了getNames()方法,返回值类型List<String>,而其子类SubA复写的getNames()方法的返回值类型可以定义为ArrayList<String>。在addUniqueMethods()方法中,这两个方法被当成不同的方法存入uniqueMethods集合中,这显然是不合理的,所以需要调用resolveGetterConflicts()方法处理这种情况,并在resolveGetterConflicts()方法中将其返回值类型填充到getTypes集合。
    resolveGetterConflicts(conflictingGetters);
  }
/***********获取当前类以及其父类中定义的所有方法的唯一签名以及Method对象*************/
 private Method[] getClassMethods(Class<?> clazz) {
    //用于记录类中定义的全部方法的唯一签名以及对应的Method对象
    Map<String, Method> uniqueMethods = new HashMap<>();
    Class<?> currentClass = clazz;
    while (currentClass != null && currentClass != Object.class) {
      //获取currentClass类中的所有方法
      addUniqueMethods(uniqueMethods, currentClass.getDeclaredMethods());
      //记录接口中定义的方法
      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[0]);//返回数组
  }

/***********为每个方法生成唯一的签名,并记录到uniqueMethods集合中*************/
private void addUniqueMethods(Map<String, Method> uniqueMethods, Method[] methods) {
    for (Method currentMethod : methods) {
      if (!currentMethod.isBridge()) {
        //获取方法签名:返回值类型#方法名称:参数类型列表。方法签名全局唯一。
        String signature = getSignature(currentMethod);
        //检查在子类中是否已经添加过该方法,如果在子类中已经添加过,则表示子类覆盖了该方法,无需再添加。
        if (!uniqueMethods.containsKey(signature)) {
          uniqueMethods.put(signature, currentMethod);
        }
      }
    }
  }
  /************************获取方法签名的方法*******************************/
  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++) {
      sb.append(i == 0 ? ':' : ',').append(parameters[i].getName());
    }
    return sb.toString();
  }

  /**************将方法签名以及其对应的Method对象存入conflictingMethods集合*********************/
  private void addMethodConflict(Map<String, List<Method>> conflictingMethods, String name, Method method) {
    List<Method> list = conflictingMethods.computeIfAbsent(name, k -> new ArrayList<>());
    list.add(method);
  }
 /**************处理协变类型返回值,同时填充getTypes集合*********************/
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()) {
        if (winner == null) {
          winner = candidate;
          continue;
        }
        Class<?> winnerType = winner.getReturnType();
        Class<?> candidateType = candidate.getReturnType();
        if (candidateType.equals(winnerType)) {
          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)) {
          // OK getter type is descendant
        } else if (winnerType.isAssignableFrom(candidateType)) {
          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(propName, winner);
    }
  }
  
  private void addGetMethod(String name, Method method) {
    if (isValidPropertyName(name)) {
      getMethods.put(name, new MethodInvoker(method));//添加Invoker
      Type returnType = TypeParameterResolver.resolveReturnType(method, type);
      getTypes.put(name, typeToClass(returnType));
    }
  }

二、ReflectorFactory

该接口主要实现了对Reflector对象的创建和缓存:

package org.apache.ibatis.reflection;

public interface ReflectorFactory {

  boolean isClassCacheEnabled();//检测ReflectorFactory对象是否会缓存Reflector对象

  void setClassCacheEnabled(boolean classCacheEnabled);//设置是否缓存Reflector对象

  Reflector findForClass(Class<?> type);//创建指定Class对应的Reflector对象
}

该接口的默认实现类:

package org.apache.ibatis.reflection;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class DefaultReflectorFactory implements ReflectorFactory {
  private boolean classCacheEnabled = true;
  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);
    }
  }

}

我们可以在配置文件中自定义自己的ReflectorFactory实现,从而扩展功能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

豢龙先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值