mybatis 反射工具箱

mybatis封装了自己的反射类工具箱。

Reflector类中:

构造方法如下:解析指定class队形,填充如下集合

public Reflector(Class<?> clazz) {
  type = clazz;//初始化clazz字段
  addDefaultConstructor(clazz);//查找clazz默认构造方法
  addGetMethods(clazz);//处理clazz中getter方法,填充getMethods集合和getTypes集合
  addSetMethods(clazz);//处理clazz中setter方法,填充setMethods集合和setTypes集合
  addFields(clazz);//处理无setter/getter方法的字段
  //根据getMethods/setMethods集合,初始化可读/写属性的名称集合
  readablePropertyNames = getMethods.keySet().toArray(new String[getMethods.keySet().size()]);
  writeablePropertyNames = setMethods.keySet().toArray(new String[setMethods.keySet().size()]);
  for (String propName : readablePropertyNames) {//初始化caseInsensitivePropertyMap(记录了所有属性名称)集合,其中记录了所有大写格式属性名称
    caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
  }
  for (String propName : writeablePropertyNames) {
    caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
  }
}

调用了

private void addDefaultConstructor(Class<?> clazz) {
  Constructor<?>[] consts = clazz.getDeclaredConstructors();//获取构造方法的参数类型
  for (Constructor<?> constructor : consts) {
    if (constructor.getParameterTypes().length == 0) {//若为无参构造函数(默认构造函数)
      if (canAccessPrivateMethods()) {//安全管理器已做检查通过则返回ture否则抛出异常返回false
        try {
          constructor.setAccessible(true);//将 accessible 标志设置为指示的布尔值,值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查,从而提高了性能。值为 false 则指示反射的对象应该实施 Java 语言访问检查。
        } catch (Exception e) {
          // Ignored. This is only a final precaution, nothing we can do.
            忽略。 这只是最后的预防措施,我们做不了什么。
        }
      }
      if (constructor.isAccessible()) {//获取上面的Accessible的flag值(true或者false)
        this.defaultConstructor = constructor;
      }
    }
  }
}

addGetMethods()解析类中定义的getter方法

先调用getClassMethods,如下所示,接着

50febb5bea73f8bc81d2b35245fb815a2e4.jpg

private Method[] getClassMethods(Class<?> cls) {//该方法获取当前类及父类中定义的所有方法的唯一签名和对应Method对象
//用于记录指定类中定义的全部方法的唯一签名及对应Method对象  
Map<String, Method> uniqueMethods = new HashMap<String, Method>();
  Class<?> currentClass = cls;
  while (currentClass != null) {
    //记录currentClass类中定义的全部方法
    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()]);//转成methods数组返回
}
//返回值类型#方法名称:参数类型列表。例如:Reflector.getSignature(Method)方法唯一签名是:java.lang.String#getSignature:java.lang.reflect.Method
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();
}
private void addUniqueMethods(Map<String, Method> uniqueMethods, Method[] methods) {//为每个方法生成唯一签名,记录到uniqueMethods集合中
  for (Method currentMethod : methods) {
    if (!currentMethod.isBridge()) {//桥接方法,JDK 1.5 引入泛型后,为了使Java的泛型方法生成的字节码和 1.5 版本前的字节码相兼容,由编译器自动生成的方法
      String signature = getSignature(currentMethod);
      // check to see if the method is already known
      // if it is known, then an extended class must have
      // overridden a method
      //检测是否在子类中已经添加了这个方法,若添加过,则表示子类覆写了这个方法,则不用再向uniqueMethods集合中添加这个方法了
      if (!uniqueMethods.containsKey(signature)) {
        if (canAccessPrivateMethods()) {//安全管理器已做检查通过则返回ture否则抛出异常返回false
          try {
            currentMethod.setAccessible(true);//将 accessible 标志设置为指示的布尔值,值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查,从而提高了性能。值为 false 则指示反射的对象应该实施 Java 语言访问检查。
          } catch (Exception e) {
            // Ignored. This is only a final precaution, nothing we can do.
           //忽略。 这只是最后的预防措施,我们做不了什么
          }
        }
        //记录该签名和方法的对应关系
        uniqueMethods.put(signature, currentMethod);
      }
    }
  }
}
/** 解决冲突 */
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();

            /* 
             * 两个方法的返回值类型一致,若两个方法返回值类型均为 boolean,则选取 isXXX 方法
             * 为 winner。否则无法决定哪个方法更为合适,只能抛出异常
             */
            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.");

                /*
                 * 如果方法返回值类型为 boolean,且方法名以 "is" 开头,
                 * 则认为候选方法 candidate 更为合适
                 */
                } else if (candidate.getName().startsWith("is")) {
                    winner = candidate;
                }

            /*
             * winnerType 是 candidateType 的子类,类型上更为具体,
             * 则认为当前的 winner 仍是合适的,无需做什么事情
             */
            } else if (candidateType.isAssignableFrom(winnerType)) {

            /*
             * candidateType 是 winnerType 的子类,此时认为 candidate 方法更为合适,
             * 故将 winner 更新为 candidate
             */
            } 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.");
            }
        }

        // 将筛选出的方法添加到 getMethods 中,并将方法返回值添加到 getTypes 中
        addGetMethod(propName, winner);
    }
}
private void addGetMethod(String name, Method method) {
  if (isValidPropertyName(name)) {//检测属性名是否合法,即属性名不能以'$'开头且不能等于'class','serialVersionUID'
    getMethods.put(name, new MethodInvoker(method));//将属性名及对应MethodInvoker对象添加到getMethods集合中
    Type returnType = TypeParameterResolver.resolveReturnType(method, type);//获取返回值type
    getTypes.put(name, typeToClass(returnType));//将属性名及getter方法返回值类型添加到getTypes集合中保存
  }
}
private void addGetMethods(Class<?> cls) {
  Map<String, List<Method>> conflictingGetters = new HashMap<String, List<Method>>();
  //conflictingGetters 集合key是属性名,value是getter方法集合,由于子类可能覆写父类getter方法,所以同一属性名会有多个getter方法
  Method[] methods = getClassMethods(cls);//获取制定类及父类和接口中定义的方法
  for (Method method : methods) {//
    if (method.getParameterTypes().length > 0) {
      continue;
    }
    String name = method.getName();
    //javaBean中getter方法的方法名长度以"get"开头并且长度大于3或者以"is"开头并且长度大于2    
    if ((name.startsWith("get") && name.length() > 3)
        || (name.startsWith("is") && name.length() > 2)) {
      name = PropertyNamer.methodToProperty(name);//截取掉get或者is获取后面实际的对应属性名称
      addMethodConflict(conflictingGetters, name, method);//若此方法在conflictingGetters中没有,则放入key是属性名 和value 是getter方法集合否则只放入list集合中的方法
    }
  }
  resolveGetterConflicts(conflictingGetters);//调用上面解决冲突的方法
}
private void addFields(Class<?> clazz) {//处理类中定义所有字段,并在处理后添加到setMethods集合,setTypes集合,getMethods集合以及getTypes集合中
  Field[] fields = clazz.getDeclaredFields();//获取clazz中定义的所有字段
  for (Field field : fields) {
    if (canAccessPrivateMethods()) {//安全管理器已做检查通过则返回ture否则抛出异常返回false
      try {
        field.setAccessible(true);//将 accessible 标志设置为指示的布尔值,值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查,从而提高了性能。值为 false 则指示反射的对象应该实施 Java 语言访问检查。
      } catch (Exception e) {
        // Ignored. This is only a final precaution, nothing we can do.
        //忽略。 这只是最后的预防措施,我们做不了什么
      }
    }
    if (field.isAccessible()) {当字段修饰符为private时,我们需要加上,否则会抛出异常
      if (!setMethods.containsKey(field.getName())) {//当setMethods集合不包含同名属性时,将其记录到setMethods集合和setTypes集合
        // 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();//该字段的修饰符
        if (!(Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers))) {//过滤掉final和static修饰的字段
          addSetField(field);//填充setMethods集合和setTypes集合,与上述addGetMethod类似
        }
      }
      if (!getMethods.containsKey(field.getName())) {//当getMethods集合不包含同名属性时,将其记录到getMethods集合和getTypes集合
        addGetField(field);//填充getMethods集合和getTypes集合,与上述addGetMethod类似
      }
    }
  }
  if (clazz.getSuperclass() != null) {//有父类
    addFields(clazz.getSuperclass());//递归调用,处理父类中定义字段
  }
}

Invoker:

public interface Invoker {
  Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException;//调用获取指定字段或执行的方法

  Class<?> getType();//返回属性相应类型
}

只有三个实现如下:

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, InvocationTargetException {
    return field.get(target);//方法返回指定对象上由此Field表示的字段的值。如果该对象具有原始类型,则该值将自动包装在对象中。
  }

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

SetFieldInvoker与GetFieldInvoker相类似

MethodInvoker的invoker调用Method.invoker实现的

 

由ReflectorFactory接口实现对Reflector对象创建与缓存

public interface ReflectorFactory {

  boolean isClassCacheEnabled();//该ReflectorFactory对象是否缓存Reflector对象

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

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

只有一个实现上述接口的实现类:DefaultReflectorFactory

public class DefaultReflectorFactory implements ReflectorFactory {
  private boolean classCacheEnabled = true;//是否开启对Reflector对象的缓存
  private final ConcurrentMap<Class<?>, Reflector> reflectorMap = new ConcurrentHashMap<Class<?>, Reflector>();//使用ConcurrentMap集合实现对
Reflector对象的缓存

  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
      Reflector cached = reflectorMap.get(type);
      if (cached == null) {
        cached = new Reflector(type);//创建Reflector对象
        reflectorMap.put(type, cached);//放入ConcurrentMap中缓存
      }
      return cached;
    } else {
      return new Reflector(type);//没开启缓存则直接创建新对象返回
    }
  }

}

 

转载于:https://my.oschina.net/u/3795791/blog/2240159

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值