mybatisMyBatis源码剖析

[MyBatis源码分析 - 反射器模块 - 组件六] Meta

2020-10-24  本文已影响0人  小胡_鸭

一、简介

  MetaClass 通过对 ReflectorPropertyTokenizer 组合使用,实现了对复杂的属性表达式的解析,并实现了获取指定属性描述信息的功能。

二、成员属性

  private ReflectorFactory reflectorFactory;
  private Reflector reflector;

三、构造方法

  // 构造方法,被静态方法#forClass内部调用
  private MetaClass(Class<?> type, ReflectorFactory reflectorFactory) {
    this.reflectorFactory = reflectorFactory;
    this.reflector = reflectorFactory.findForClass(type);
  }

  这是一个私有构造方法,构造函数会被静态内部类 #forClass() 调用。

四、方法功能

1、MetaClass forClass(Class<?> type, ReflectorFactory reflectorFactory)

【功能】创建指定类的 MetaClass 对象(创建 Reflector 对象的工厂对象可以用户指定)。
【源码与注解】

  // 根据传入的Class对象和反射工厂对象创建对应的MetaClass对象
  public static MetaClass forClass(Class<?> type, ReflectorFactory reflectorFactory) {
    return new MetaClass(type, reflectorFactory);
  }

2、MetaClass metaClassForProperty(String name)

【功能】根据指定的类属性名创建类属性类型对应的MataClass对象。
【源码与注解】

  // 根据类属性名创建类属性类型对应的MataClass对象
  public MetaClass metaClassForProperty(String name) {
    // 从类的反射器对象中找到对应的类属性的类型
    Class<?> propType = reflector.getGetterType(name);
    // 创建属性对应的MetaClass对象
    return MetaClass.forClass(propType, reflectorFactory);
  }

3、String findProperty(String name)

【功能】根据表达式,获得属性
【源码与注解】

  public String findProperty(String name) {
    // 将表达式委托给 #buildProperty 方法处理
    StringBuilder prop = buildProperty(name, new StringBuilder());
    return prop.length() > 0 ? prop.toString() : null;
  }

4、StringBuilder buildProperty(String name, StringBuilder builder)

【功能】递归处理属性表达式,并将处理结果返回给 #findProperty() 方法。
【源码与注解】

  private StringBuilder buildProperty(String name, StringBuilder builder) {
    PropertyTokenizer prop = new PropertyTokenizer(name);     // 解析属性表达式
    // (1) 判断是否有子表达式
    if (prop.hasNext()) {
      // (1.1) 查找 PropertyTokenizer.name 对应的属性
      String propertyName = reflector.findPropertyName(prop.getName());
      if (propertyName != null) {
        builder.append(propertyName);   // 追加属性
        builder.append(".");
        // (1.2) 为该属性创建对应的MetaClass对象
        MetaClass metaProp = metaClassForProperty(propertyName);
        // (1.3) 递归解析 PropertyTokenizer.children 字段,并将解析结果添加到 builder 中保存
        metaProp.buildProperty(prop.getChildren(), builder);
      }
    } else {
      // (2) 递归出口
      String propertyName = reflector.findPropertyName(name);
      if (propertyName != null) {
        builder.append(propertyName);
      }
    }
    return builder;
  }

  比如属性表达式 order[0].items[0].name,第一次执行方法时,解析到 propertyName 为 order,children 为 items[0].name,递归调用;第二次调用 propertyName 为 items,children 为 name,递归调用;第三次进入递归出口分支,propertyName 为 name;所以最后返回的 builder 为 order.items.name

5、String findProperty(String name, boolean useCamelCaseMapping)

【功能】在 #findProperty(String) 的基础上增加了是否使用驼峰转换的标志位,如果属性名是按照驼峰的规则,则先去除掉下划线。
【源码】

  public String findProperty(String name, boolean useCamelCaseMapping) {
    if (useCamelCaseMapping) {
      name = name.replace("_", "");
    }
    return findProperty(name);
  }

6、Class<?> getSetterType(String name)

【功能】获取属性表达式中的属性对应 setter 方法的类型。
【源码与注解】

  public Class<?> getSetterType(String name) {
    // 解析属性表达式
    PropertyTokenizer prop = new PropertyTokenizer(name);
    // 判断是否存在待处理的子表达式
    if (prop.hasNext()) {
      // 获取顶层属性对应的 MetaClass 对象,递归调用
      MetaClass metaProp = metaClassForProperty(prop.getName());
      return metaProp.getSetterType(prop.getChildren());
    } else {
      // 不存在子表达式,直接根据属性名从 reflector 中获取属性 setter 类型
      return reflector.getSetterType(prop.getName());
    }
  }

7、Class<?> getGetterType(String name)

【功能】获取属性表达式中的属性对应 getter 方法的类型。
【源码】

  public Class<?> getGetterType(String name) {
    PropertyTokenizer prop = new PropertyTokenizer(name);
    if (prop.hasNext()) {
      MetaClass metaProp = metaClassForProperty(prop);
      return metaProp.getGetterType(prop.getChildren());
    }
    // issue #506. Resolve the type inside a Collection Object
    return getGetterType(prop);
  }

【解析】
  上面部分代码的处理跟 #getSetterType() 方法的处理类似,当解析到属性表达式没有子表达式时,递归出口调用 #getGetterType(PropertyTokenizer) 方法处理,该方法主要用来处理要获取的属性是在集合中的情况如 order['id'](但这里其实我也有点疑惑,为什么 #getSetterType() 方法就不用这样处理呢?)

8、Class<?> getGetterType(PropertyTokenizer prop)

【功能】解析带泛型的 getterType 的真正类型
【源码与注解】

  private Class<?> getGetterType(PropertyTokenizer prop) {
    // 获取表达式中顶层属性的类型
    Class<?> type = reflector.getGetterType(prop.getName());
    // 如果表达式中使用了下标,并且顶层属性的是 Collection 的子类
    if (prop.getIndex() != null && Collection.class.isAssignableFrom(type)) {
      // 通过 TypeParameterResolver 工具类解析属性的类型
      Type returnType = getGenericGetterType(prop.getName());
      // 针对 ParameterizedType 进行处理,即针对泛型集合类型进行处理
      if (returnType instanceof ParameterizedType) {
        Type[] actualTypeArguments = ((ParameterizedType) returnType).getActualTypeArguments();   // 获取实际的类型参数
        if (actualTypeArguments != null && actualTypeArguments.length == 1) {   // 过滤掉多个实际参数类型的情况,是因为表达式表示的属性类型,是对应一个参数类型的集合
          returnType = actualTypeArguments[0];    // 获取泛型的类型
          if (returnType instanceof Class) {
            type = (Class<?>) returnType;
          } else if (returnType instanceof ParameterizedType) {
            type = (Class<?>) ((ParameterizedType) returnType).getRawType();
          }
        }
      }
    }
    // 如果没使用下标,或者解析完毕,返回对应的类型
    return type;
  }

【解析】
  比如 order[0] 没有子表达式,会调用本方法处理,假设 order 属性的类型为 List<String>,则 order[0] 表示列表中的第一个元素,其属性类型应为 String。

9、Type getGenericGetterType(String propertyName)

【功能】获取属性对应泛型类型中的泛型的具体类型
【源码与注解】

  private Type getGenericGetterType(String propertyName) {
    try {
      // 获取属性对应的 getInvoker
      Invoker invoker = reflector.getGetInvoker(propertyName);
      // 如果 invoker 是一个 MethodInvoker,即有对应 getter,获取对应的 Method
      // 并调用 TypeParameterResolver.resolveReturnType 处理
      if (invoker instanceof MethodInvoker) {
        Field _method = MethodInvoker.class.getDeclaredField("method");
        _method.setAccessible(true);
        Method method = (Method) _method.get(invoker);
        return TypeParameterResolver.resolveReturnType(method, reflector.getType());
      // 如果 invoker 是一个 GetFieldInvoker,即 invoker 中封装的是一个 Field,则获取对应的 Field
      // 并调用 TypeParameterResolver.resolveFieldType 处理
      } else if (invoker instanceof GetFieldInvoker) {
        Field _field = GetFieldInvoker.class.getDeclaredField("field");
        _field.setAccessible(true);
        Field field = (Field) _field.get(invoker);
        return TypeParameterResolver.resolveFieldType(field, reflector.getType());
      }
    } catch (NoSuchFieldException e) {
    } catch (IllegalAccessException e) {
    }
    return null;
  }

10、MetaClass metaClassForProperty(PropertyTokenizer prop)

【功能】根据当前类的一个属性表达式,创建表达式中表示的属性对应的 MetaClass 对象。
【源码与注解】

  private MetaClass metaClassForProperty(PropertyTokenizer prop) {
    // 获取表达式中属性的真正类型
    Class<?> propType = getGetterType(prop);
    // 创建 MetaClass 对象
    return MetaClass.forClass(propType, reflectorFactory);
  }

11、boolean hasSetter(String name)

【功能】判断表达式对应的属性是否允许设置值。
【源码与注解】

public boolean hasSetter(String name) {
  PropertyTokenizer prop = new PropertyTokenizer(name);   // 解析属性表达式
  if (prop.hasNext()) {   // 判断是否有子表达式
    // 如果类中并没有顶层属性对应的 setter,直接返回false,若有则递归解析表达式并且递归调用本方法
    if (reflector.hasSetter(prop.getName())) {
      MetaClass metaProp = metaClassForProperty(prop.getName());
      return metaProp.hasSetter(prop.getChildren());
    } else {
      return false;
    }
  } else {
    // 如果没有子表达式,或者递归的出口,根据属性名调用反射器的方法返回
    return reflector.hasSetter(prop.getName());
  }
}

12、boolean hasGetter(String name)

【功能】判断表达式对应的属性是否允许获取值。
【源码与注解】跟 #hasSetter() 类型,不赘述。

  public boolean hasGetter(String name) {
    PropertyTokenizer prop = new PropertyTokenizer(name);
    if (prop.hasNext()) {
      if (reflector.hasGetter(prop.getName())) {
        MetaClass metaProp = metaClassForProperty(prop);
        return metaProp.hasGetter(prop.getChildren());
      } else {
        return false;
      }
    } else {
      return reflector.hasGetter(prop.getName());
    }
  }

13、其他方法

【功能】代理调用 Reflector 的方法。

五、测试案例

1、案例1

(1)类定义

// 泛型接口
public interface GenericInterface<K> {
  void setId(K id);
}
// 泛型抽象类
public abstract class GenericAbstract<K> {
  public abstract K getId();
}
// 继承泛型抽象类并具体化类型的抽象类
public abstract class GenericSubclass extends GenericAbstract<Long> {
  @Override
  public abstract Long getId();
}
// 实现泛型接口和继承泛型抽象类的类
public class GenericConcrete extends GenericSubclass implements GenericInterface<Long> {
  private Long id;

  @Override
  public Long getId() {
    return id;
  }

  public void setId(String id) {
    this.id = Long.valueOf(id);
  }

  @Override
  public void setId(Long id) {
    this.id = id;
  }

  public void setId(Integer id) {
    this.id = (long) id;
  }
}

(2)测试代码

  @Test
  public void shouldTestDataTypeOfGenericMethod() {
    ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
    MetaClass meta = MetaClass.forClass(GenericConcrete.class, reflectorFactory);
    assertEquals(Long.class, meta.getGetterType("id"));
    assertEquals(Long.class, meta.getSetterType("id"));
  }

(3)执行结果



2、案例2

(1)类定义

public class RichType {

  private RichType richType;

  private String richField;

  private String richProperty;

  private Map richMap = new HashMap();

  private List richList = new ArrayList() {
    {
      add("bar");
    }
  };

  public RichType getRichType() {
    return richType;
  }

  public void setRichType(RichType richType) {
    this.richType = richType;
  }

  public String getRichProperty() {
    return richProperty;
  }

  public void setRichProperty(String richProperty) {
    this.richProperty = richProperty;
  }

  public List getRichList() {
    return richList;
  }

  public void setRichList(List richList) {
    this.richList = richList;
  }

  public Map getRichMap() {
    return richMap;
  }

  public void setRichMap(Map richMap) {
    this.richMap = richMap;
  }
}

(2)测试代码

  // 测试 hasGetter 方法
  @Test
  public void shouldCheckGetterExistance() {
    ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
    MetaClass meta = MetaClass.forClass(RichType.class, reflectorFactory);
    assertTrue(meta.hasGetter("richField"));
    assertTrue(meta.hasGetter("richProperty"));
    assertTrue(meta.hasGetter("richList"));
    assertTrue(meta.hasGetter("richMap"));
    assertTrue(meta.hasGetter("richList[0]"));

    assertTrue(meta.hasGetter("richType"));
    assertTrue(meta.hasGetter("richType.richField"));
    assertTrue(meta.hasGetter("richType.richProperty"));
    assertTrue(meta.hasGetter("richType.richList"));
    assertTrue(meta.hasGetter("richType.richMap"));
    assertTrue(meta.hasGetter("richType.richList[0]"));

    assertFalse(meta.hasGetter("[0]"));
  }

  // 测试 hasSetter 方法
  @Test
  public void shouldCheckSetterExistance() {
    ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
    MetaClass meta = MetaClass.forClass(RichType.class, reflectorFactory);
    assertTrue(meta.hasSetter("richField"));
    assertTrue(meta.hasSetter("richProperty"));
    assertTrue(meta.hasSetter("richList"));
    assertTrue(meta.hasSetter("richMap"));
    assertTrue(meta.hasSetter("richList[0]"));

    assertTrue(meta.hasSetter("richType"));
    assertTrue(meta.hasSetter("richType.richField"));
    assertTrue(meta.hasSetter("richType.richProperty"));
    assertTrue(meta.hasSetter("richType.richList"));
    assertTrue(meta.hasSetter("richType.richMap"));
    assertTrue(meta.hasSetter("richType.richList[0]"));

    assertFalse(meta.hasSetter("[0]"));
  }

  // 测试 getGetterType 方法
  @Test
  public void shouldCheckTypeForEachGetter() {
    ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
    MetaClass meta = MetaClass.forClass(RichType.class, reflectorFactory);
    assertEquals(String.class, meta.getGetterType("richField"));
    assertEquals(String.class, meta.getGetterType("richProperty"));
    assertEquals(List.class, meta.getGetterType("richList"));
    assertEquals(Map.class, meta.getGetterType("richMap"));
    assertEquals(List.class, meta.getGetterType("richList[0]"));

    assertEquals(RichType.class, meta.getGetterType("richType"));
    assertEquals(String.class, meta.getGetterType("richType.richField"));
    assertEquals(String.class, meta.getGetterType("richType.richProperty"));
    assertEquals(List.class, meta.getGetterType("richType.richList"));
    assertEquals(Map.class, meta.getGetterType("richType.richMap"));
    assertEquals(List.class, meta.getGetterType("richType.richList[0]"));
  }

  // 测试 getSetterType 方法
  @Test
  public void shouldCheckTypeForEachSetter() {
    ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
    MetaClass meta = MetaClass.forClass(RichType.class, reflectorFactory);
    assertEquals(String.class, meta.getSetterType("richField"));
    assertEquals(String.class, meta.getSetterType("richProperty"));
    assertEquals(List.class, meta.getSetterType("richList"));
    assertEquals(Map.class, meta.getSetterType("richMap"));
    assertEquals(List.class, meta.getSetterType("richList[0]"));

    assertEquals(RichType.class, meta.getSetterType("richType"));
    assertEquals(String.class, meta.getSetterType("richType.richField"));
    assertEquals(String.class, meta.getSetterType("richType.richProperty"));
    assertEquals(List.class, meta.getSetterType("richType.richList"));
    assertEquals(Map.class, meta.getSetterType("richType.richMap"));
    assertEquals(List.class, meta.getSetterType("richType.richList[0]"));
  }

  // 测试 getGetterNames 和 getSetterNames 方法
  @Test
  public void shouldCheckGetterAndSetterNames() {
    ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
    MetaClass meta = MetaClass.forClass(RichType.class, reflectorFactory);
    assertEquals(5, meta.getGetterNames().length);
    assertEquals(5, meta.getSetterNames().length);
  }

  // 测试 findProperty 方法
  @Test
  public void shouldFindPropertyName() {
    ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
    MetaClass meta = MetaClass.forClass(RichType.class, reflectorFactory);
    assertEquals("richField", meta.findProperty("RICHfield"));
  }

(3)执行结果

上一篇 下一篇

猜你喜欢

热点阅读