Mybatis框架基础支持层——反射工具箱之MetaClass
Posted wly1-6
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis框架基础支持层——反射工具箱之MetaClass相关的知识,希望对你有一定的参考价值。
简介:MetaClass是Mybatis对类级别的元信息的封装和处理,通过与属性工具类的结合, 实现了对复杂表达式的解析,实现了获取指定描述信息的功能
public class MetaClass { private ReflectorFactory reflectorFactory; private Reflector reflector; /** * 构造函数私有 */ private MetaClass(Class<?> type, ReflectorFactory reflectorFactory) { this.reflectorFactory = reflectorFactory; this.reflector = reflectorFactory.findForClass(type); } /** * 调用构造方法创建MetaClass */ public static MetaClass forClass(Class<?> type, ReflectorFactory reflectorFactory) { return new MetaClass(type, reflectorFactory); } /** * 通过属性名称, 获取属性的MetaClass(解决成员变量是类的情况) */ 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(); } 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()); } } 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); } 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 e) { } catch (IllegalAccessException e) { } 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); } /** * 解析属性表达式 会去寻找reflector中是否有对应的的属性 */ 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 对象 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(); } }
理解了这个方法(递归, 该类中有很多类似的), 就可以很好的对这个类进行理解, 以查找(richType.richProperty)为例:
- 通过 PropertyTokenizer 对表达式进行解析, 得到当前的 name = richType, children = richProperty
- 从 reflector 中查找该 richType 属性
- 将 richType 添加到 builder 中
- 使用 metaClassForProperty 创建 richType 的 MetaClass。
- 递归调用自身来处理子表达式
退出的条件就是没有子表达式。 这个就是为了, 我们类中有成员变量是类, 我们可以通过其找到他们的所有类及其属性。
注意, 在此过程中, ReflectorFactory 一直是同一个, 而其内部缓存了多个 Reflector 对象。
以上是关于Mybatis框架基础支持层——反射工具箱之MetaClass的主要内容,如果未能解决你的问题,请参考以下文章
带你彻底搞懂MyBatis的底层实现之反射工具箱(reflector)
带你彻底搞懂MyBatis的底层实现之反射工具箱(reflector)