mybatis源码reflection包--反射核心类reflector

Reflector是reflection包中最核心的一个类,负责对一个类的进行反射解析,并将解析后的结果存到属性中。

Reflector中的属性如下:

// 要被反射解析的类
  private final Class<?> type;
  // 能够读的属性列表,即有get方法的属性列表
  private final String[] readablePropertyNames;
  // 能够写的属性列表,即有set方法的属性列表
  private final String[] writablePropertyNames;
  // set方法映射表。键为属性名,值为对应的set方法
  private final Map<String, Invoker> setMethods = new HashMap<>();
  // get方法映射表。键为属性名,值为对应的get方法
  private final Map<String, Invoker> getMethods = new HashMap<>();
  // set方法输入类型。键为属性名,值为对应的该属性的set方法的类型(实际为set方法的第一个参数的类型)
  private final Map<String, Class<?>> setTypes = new HashMap<>();
  // get方法输出类型。键为属性名,值为对应的该属性的set方法的类型(实际为set方法的返回值类型)
  private final Map<String, Class<?>> getTypes = new HashMap<>();
  // 默认构造函数
  private Constructor<?> defaultConstructor;
  // 大小写无关的属性映射表。键为属性名全大写值,值为属性名
  private Map<String, String> caseInsensitivePropertyMap = new HashMap<>();

Reflector的反射解析实在构造器中进行的 ,会将该类的属性 方法等一一归类到属性中 如下所示:

  /**
   * Reflector的构造方法
   * @param clazz 需要被反射处理的目标类
   */
  public Reflector(Class<?> clazz) {
    // 要被反射解析的类
    type = clazz;
    // 设置默认构造器属性
    addDefaultConstructor(clazz);
    // 解析所有的getter
    addGetMethods(clazz);
    // 解析所有有setter
    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);
    }
  }

分析一下addGetMethods的逻辑:

conflictingGetters的key是方法名解析后的属性名,V是对应的方法列表。同一个属性可能有多个方法 例如name属性对应 getName() isName() 两个方法,List<Method>里边就存了俩。
  private void addGetMethods(Class<?> clazz) {
    // 存储属性的get方法。Map的键为属性名,值为get方法列表。某个属性的get方法用列表存储是因为前期可能会为某一个属性找到多个可能get方法。
    Map<String, List<Method>> conflictingGetters = new HashMap<>();
    
    // 找出该类中所有的方法
    Method[] methods = getClassMethods(clazz);
    // 过滤出get方法,过滤条件有:无入参、符合Java Bean的命名规则;然后取出方法对应的属性名、方法,放入conflictingGetters
    Arrays.stream(methods).filter(m -> m.getParameterTypes().length == 0 && PropertyNamer.isGetter(m.getName()))
      .forEach(m -> addMethodConflict(conflictingGetters, PropertyNamer.methodToProperty(m.getName()), m));
    // 如果一个属性有多个疑似get方法,resolveGetterConflicts用来找出合适的那个
    resolveGetterConflicts(conflictingGetters);
  }
resolveGetterConflicts用来处理多个疑似的get方法,如果一个属性有多个getter方法,该方法负责找出真正的 如果有重复get方法 返回值不一样 也不是继承关系 就会报错
  // 如果一个属性有多个getter方法,该方法负责找出真正的 如果有重复get方法 返回值不一样 也不是继承关系 就会报错
  private void resolveGetterConflicts(Map<String, List<Method>> conflictingGetters) {
    for (Entry<String, List<Method>> entry : conflictingGetters.entrySet()) {
      Method winner = null;
      String propName = entry.getKey();
      // 对key的多个getter进行循环
      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)) {
            // 不是布尔型,两个返回一样,则无法辨明到底哪个是getter
            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")) {
            // 是is的当选
            winner = candidate;
          }
        } else if (candidateType.isAssignableFrom(winnerType)) {
          // candidateType返回了子类,则winner作为最终结果
        } else if (winnerType.isAssignableFrom(candidateType)) {
          // winner返回了子类,则candidate作为最终结果
          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.");
        }
      }
      // 最后放入的是 属性:唯一的getter方法
      addGetMethod(propName, winner);
    }
  }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值