mybatis初始化配置——反射組件

 這篇我準備介紹下mybatis另一個基礎支撐組件,反射組件組。

1、Reflector

我們來看下Reflector類的屬性和構造器,通過屬性和構造器我們基本上就能瞭解Reflector這個類了

public class Reflector {

  private final Class<?> type;
  private final String[] readablePropertyNames;
  private final String[] writeablePropertyNames;
  private final Map<String, Invoker> setMethods = new HashMap<>();
  private final Map<String, Invoker> getMethods = new HashMap<>();
  private final Map<String, Class<?>> setTypes = new HashMap<>();
  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()]);
    writeablePropertyNames = setMethods.keySet().toArray(new String[setMethods.keySet().size()]);
    for (String propName : readablePropertyNames) {
      caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
    }
    for (String propName : writeablePropertyNames) {
      caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
    }
  }
}

首先我們要知道,一個類對象創建一個對應的Reflector,這個Reflector可以操作類,及這個類創建的對象

我們來解釋一下上面的屬性

type:類對象對應的Class類型

readablePropertyNames: 類對象對應的可讀屬性集合
writeablePropertyNames:類對象對應的可寫屬性集合
setMethods:類對象的set方法集合
getMethods:類對象的get方法集合

setType:類對象的set類型集合

getType:類對象的get類型集合

defaultConstructor:類對象的默認構造器

caseInsensitivePropertyMap: 記錄了所有屬性集合

我們再來看下Reflector的構造器

構造器就是獲取類對象的默認構造器、get方法集合、set方法集合,可讀屬性集合、可寫屬性集合

我們用一個示例來看看這個一個類對象被這個對象構造後的結果:

public class SysUser {
    private String name;
    private Integer age;

    private String sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

public static void main(String[] args) {
        Reflector reflector = new Reflector(SysUser.class);
    }

上面代碼構造了SysUser的Reflector之後,Reflector的每個屬性對應如下

type: SysUser.class

readablePropertyNames:["sex", "name", "age"]

writeablePropertyNames:["sex", "name", "age"]

setMethods:[{sex, SetFieldInvoker}, {name, MethodInvoker}, {age, MethodInvoker}]

getMethod:[{sex, GetFieldInvoker}, {name, MethodInvoker}, {age, MethodInvoker}]

setTypes:[{sex, String}, {name, String}, {age, Integer}]

getTypes:[{sex, String}, {name, String}, {age, Integer}]

defaultConstructor: SysUser的默認構造器

ReflectorFactory

public interface ReflectorFactory {

  boolean isClassCacheEnabled();

  void setClassCacheEnabled(boolean classCacheEnabled);

  Reflector findForClass(Class<?> type);
}

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) {
            
      return reflectorMap.computeIfAbsent(type, Reflector::new);
    } else {
      return new Reflector(type);
    }
  }

}

上面代碼是ReflectorFactory的接口和默認實現:

其主要就是提供創建Reflector及緩存Reflector的功能

PropertyTokenizer

針對user.order[0].orderId這種複雜的表達式,mybatis提供了一個PropertyTokenizer解析,我們來看下PropertyTokenizer的結構

propertyTokenizer是一個迭代器。

我們在看看其實現

public class PropertyTokenizer implements Iterator<PropertyTokenizer> {
  private String name;
  private final String indexedName;
  private String index;
  private final String children;

// 找到第一個.讀出【】之間的index,最終生成一個名稱一個索引,例如order[0],name=order,index=0
  public PropertyTokenizer(String fullname) {
    int delim = fullname.indexOf('.');
    if (delim > -1) {
      name = fullname.substring(0, delim);
      children = fullname.substring(delim + 1);
    } else {
      name = fullname;
      children = null;
    }
    indexedName = name;
    delim = name.indexOf('[');
    if (delim > -1) {
      index = name.substring(delim + 1, name.length() - 1);
      name = name.substring(0, delim);
    }
  }

  public String getName() {
    return name;
  }

  public String getIndex() {
    return index;
  }

  public String getIndexedName() {
    return indexedName;
  }

  public String getChildren() {
    return children;
  }

  @Override
  public boolean hasNext() {
    return children != null;
  }

  @Override
  public PropertyTokenizer next() {
    return new PropertyTokenizer(children);
  }
}

改組件功能就是解析屬性,找到第一個.讀出【】之間的index,最終生成一個名稱一個索引。

例如order[0],name=order,index=0

我們可以來解析一段字符串,來看看PropertyTokenizer的用法

public class PropertyTokenizerDemo {
    public static void main(String[] args) {
        String prop = "user.order[0].item[0].name";

        parseProperty(prop);
    }
    public static void parseProperty(String prop){
        PropertyTokenizer pt = new PropertyTokenizer(prop);

        if (pt.hasNext()) {
            System.out.println(pt.getName()+" "+pt.getIndex());
            parseProperty(pt.getChildren());
        }
    }
    // 輸出結果
user null
order 0
item 0
}

可見其用法和list的iterator差不多

MetaClass

通過Reflector和PropertyTokenizer,實現對複雜屬性表達式的解析。

public class MetaClass {

  private final ReflectorFactory reflectorFactory;
  private final Reflector reflector;

  private MetaClass(Class<?> type, ReflectorFactory reflectorFactory) {
    this.reflectorFactory = reflectorFactory;
    this.reflector = reflectorFactory.findForClass(type);
  }

  public static MetaClass forClass(Class<?> type, ReflectorFactory reflectorFactory) {
    return new MetaClass(type, reflectorFactory);
  }

  public MetaClass metaClassForProperty(String name) {
    Class<?> propType = reflector.getGetterType(name);
    return MetaClass.forClass(propType, reflectorFactory);
  }

    // 獲取屬性
  public String findProperty(String name) {
    StringBuilder prop = buildProperty(name, new StringBuilder());
    return prop.length() > 0 ? prop.toString() : null;
  }

  public String findProperty(String name, boolean useCamelCaseMapping) {
    if (useCamelCaseMapping) {
      name = name.replace("_", "");
    }
    return findProperty(name);
  }
// 獲取所有可讀屬性
  public String[] getGetterNames() {
    return reflector.getGetablePropertyNames();
  }
// 獲取所有可寫屬性
  public String[] getSetterNames() {
    return reflector.getSetablePropertyNames();
  }
// 獲取name名稱對應屬性類型
  public Class<?> getSetterType(String name) {
    PropertyTokenizer prop = new PropertyTokenizer(name);
    if (prop.hasNext()) {
      MetaClass metaProp = metaClassForProperty(prop.getName());
      return metaProp.getSetterType(prop.getChildren());
    } else {
      return reflector.getSetterType(prop.getName());
    }
  }
// 獲取name名稱對應屬性類型
  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);
  }
// 根據PropertyTokenizer創建MetaClass
  private MetaClass metaClassForProperty(PropertyTokenizer prop) {
    Class<?> propType = getGetterType(prop);
    return MetaClass.forClass(propType, reflectorFactory);
  }

  private Class<?> getGetterType(PropertyTokenizer prop) {
    Class<?> type = reflector.getGetterType(prop.getName());
    if (prop.getIndex() != null && Collection.class.isAssignableFrom(type)) {
      Type returnType = getGenericGetterType(prop.getName());
      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;
  }

  private Type getGenericGetterType(String propertyName) {
    try {
      Invoker invoker = reflector.getGetInvoker(propertyName);
      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());
      } 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 | IllegalAccessException ignored) {
    }
    return null;
  }

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

  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());
    }
  }

  public Invoker getGetInvoker(String name) {
    return reflector.getGetInvoker(name);
  }

  public Invoker getSetInvoker(String name) {
    return reflector.getSetInvoker(name);
  }
// 構造屬性
  private StringBuilder buildProperty(String name, StringBuilder builder) {
    PropertyTokenizer prop = new PropertyTokenizer(name);
    if (prop.hasNext()) {
      String propertyName = reflector.findPropertyName(prop.getName());
      if (propertyName != null) {
        builder.append(propertyName);
        builder.append(".");
        MetaClass metaProp = metaClassForProperty(propertyName);
        metaProp.buildProperty(prop.getChildren(), builder);
      }
    } else {
      String propertyName = reflector.findPropertyName(name);
      if (propertyName != null) {
        builder.append(propertyName);
      }
    }
    return builder;
  }
// 是否有默認方法
  public boolean hasDefaultConstructor() {
    return reflector.hasDefaultConstructor();
  }

}

我們通過一個複雜的屬性,並創建其MetaClass的示例來了解MetaClass

額,這個例子簡單化有點搞不定,搞定了也是類似於這個一樣複雜,分析一個例子流程圖吧:

例子代碼下載

類實例如下

public class SysUser {
    private String name;
    private Integer age;
    private Order order;
    private String sex;
}
public class Order {
    private String orderId;
    private Prod prod;
}
public class Prod {
    private String name;
    private Double price;
}

以獲取SysUser的order.prod爲例

sysUserMetaObject.getValue("order.prod")

1)  PropertyTokenizer prop = new PropertyTokenizer("order.prod"); prod.hasNext()爲true

2) metaObjectForProperty(”order"),這裏面是一個遞歸調用

       a) 這裏getValue("order"), 再次回到了第一步new PropertyTokenizer("order"), prod.hasNext()爲false

       b) objectWrapper.get(“order”);

            aa) getBeanProperty() 獲取getInvoker, 調用invoker,獲取該對象對應的屬性值,這裏是order對象

           bb)  返回了一個Order對象

      c) MetaObject.forObject創建一個Order對象的MetaObject

3)如果是空,返回空,否則調用order對象的MetaObject的getValue(),即orderMetaObject.getValue("prod")

以此類推最後返回一個prod對象

這兩個類之間關係確實比較複雜,類內部方法遞歸,類之間方法遞歸

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章