Mybatis源码解析——反射工具箱

mac2024-05-23  34

反射工具箱

Reflector

一个Class类对应的Reflector对象包括:

//对应的Class类型 private final Class<?> type; //可读属性(有get方法的)名字数组 private final String[] readablePropertyNames; //可写属性(有set方法的)名字数组 private final String[] writeablePropertyNames; //set方法,key为属性名称,value是Invoker对象(对set方法对应的method对象的封装) private final Map<String, Invoker> setMethods = new HashMap<String, Invoker>(); //get方法 private final Map<String, Invoker> getMethods = new HashMap<String, Invoker>(); //set方法的参数类型 private final Map<String, Class<?>> setTypes = new HashMap<String, Class<?>>(); //get方法的返回值类型 private final Map<String, Class<?>> getTypes = new HashMap<String, Class<?>>(); //默认构造器 private Constructor<?> defaultConstructor; //所有属性名称,全大写形式 private Map<String, String> caseInsensitivePropertyMap = new HashMap<String, String>();

以上属性会在构造方法中进行填充

public Reflector(Class<?> clazz) { type = clazz; addDefaultConstructor(clazz); addGetMethods(clazz); addSetMethods(clazz); addFields(clazz);//没有set/get方法时会使用Field操作 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); } }
addGetMethods
private void addGetMethods(Class<?> cls) { Map<String, List<Method>> conflictingGetters = new HashMap<String, List<Method>>(); Method[] methods = getClassMethods(cls); for (Method method : methods) { if (method.getParameterTypes().length > 0) { continue; } String name = method.getName(); if ((name.startsWith("get") && name.length() > 3) || (name.startsWith("is") && name.length() > 2)) { name = PropertyNamer.methodToProperty(name); addMethodConflict(conflictingGetters, name, method); } } resolveGetterConflicts(conflictingGetters); }

其流程图如图所示

ReflectorFactory

主要提供Reflector对象的创建和缓存,使用concurrentMap缓存对象,key为类

TypeParamterResolver

Type接口的实现类:

ClassParameterizedType:参数化类型,如List<String> Type getRawType():返回参数化类型中的原始类型;如List<String>返回ListType[] getActualTypeArguments():返回类型变量或实际类型列表,如List<String>返回StringType getOwnerType():返回类型所属关系;如A<T>类的内部类Inner<T>的类型为A<T> GenericArrayType:数组类型且组成元素是ParameterizedType或TypeVariable;如List<String>[] Type getGenericComponentType():返回数组组成的元素 TypeVariable:类型变量,反应JVM编译该泛型前的信息 Type[] getBounds():获取类型变量的上边界,未声明则为Object;如Test<K extends Person>中K的上界为PersionD getGenericDeclaration():获取声明该类型变量的原始类型;如Test<K extends Person>原始类型为TestString getName():获取在源码中定义时的名字,Test<K extends Person>中为K WildcardType:表示通配符泛型如? super Integer Type[] getUpperBounds():返回范型变量上届Type[] getLowerBounds():返回范型变量下届

ObjectFactory

用来创建对象的工厂,默认实现DefaultObjectFactory其create()调用instantiateClass(),最终调用Constructor.newInstance()

Property工具集

PropertyTokenizer负责解析表达式,可以迭代处理PropertyNamer负责将方法名转换为属性名(去掉is\set\get等前缀并首字母小写)以及检测是否是set、get方法或属性PropertyCopier同类型的Bean的属性值拷贝,核心方法为copyBeanProperties() <resultMap id = "base" type="User"> <id column = "id" property="id"/> <result column = "item" property="orders[0].items[0].name"/> </result>

分解过程如图所示

MetaClass

使用Reflector和PropertyTokenizer组合实现对复杂属性表达式的解析 MetaClass的构造函数接收一个类并为这个类构建Reflector对象 MetaClass.findProperty()会调用buildProperty(),最终通过PropertyTokenizer解析复杂属性表达式 PropertyTokenizer的解析方式见上文,MetaClass.hasGetter()和MetaClass.hasSetter()最终都是通过Reflector来实现的

ObjectWrapper

MetaClass是对类级别元信息的封装和处理,ObjectWrapper是对对象的包装,定义了一系列查询对象属性,更新属性的方法

public interface ObjectWrapper { Object get(PropertyTokenizer prop); void set(PropertyTokenizer prop, Object value); String findProperty(String name, boolean useCamelCaseMapping); String[] getGetterNames(); String[] getSetterNames(); Class<?> getSetterType(String name); Class<?> getGetterType(String name); boolean hasSetter(String name); boolean hasGetter(String name); MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory); boolean isCollection(); void add(Object element); <E> void addAll(List<E> element); }

其继承UML图如图所示

BaseWrapper是抽象类,封装了MetaObject对象,并提供了三种方法

getCollectionValuesetCollectionValueresolverCollection:会调用MetaObject.getValue()

getCollectionValue会根据PropertyTokenizer中的index取值

protected Object getCollectionValue(PropertyTokenizer prop, Object collection) { if (collection instanceof Map) { return ((Map) collection).get(prop.getIndex()); } else { int i = Integer.parseInt(prop.getIndex()); if (collection instanceof List) { return ((List) collection).get(i); } else if (collection instanceof Object[]) { return ((Object[]) collection)[i]; } else if (collection instanceof char[]) { return ((char[]) collection)[i]; } else if (collection instanceof boolean[]) { return ((boolean[]) collection)[i]; } else if (collection instanceof byte[]) { return ((byte[]) collection)[i]; } else if (collection instanceof double[]) { return ((double[]) collection)[i]; } else if (collection instanceof float[]) { return ((float[]) collection)[i]; } else if (collection instanceof int[]) { return ((int[]) collection)[i]; } else if (collection instanceof long[]) { return ((long[]) collection)[i]; } else if (collection instanceof short[]) { return ((short[]) collection)[i]; } else { throw new ReflectionException("The '" + prop.getName() + "' property of " + collection + " is not a List or Array."); } } }

BeanWrapper针对的是javaBean

public Object get(PropertyTokenizer prop) { //存在索引信息 if (prop.getIndex() != null) { //拿到集合对象 Object collection = resolveCollection(prop, object); //获取对应索引处的值 return getCollectionValue(prop, collection); } else { //通过metaClass操作反射get方法 return getBeanProperty(prop, object); } }

MetaObject

完成对属性表达式解析的过程,最上层

//原始JavaBean对象 private final Object originalObject; //JavaBean的ObjectWrapper对象 private final ObjectWrapper objectWrapper; //实例化originalObject的工厂 private final ObjectFactory objectFactory; private final ObjectWrapperFactory objectWrapperFactory; private final ReflectorFactory reflectorFactory;

MetaObject的构造方法会根据传入的原始对象类型以及ObjectFactory 的实现创建相应ObjectWrapper 对象 MetaObject和ObjectWrapper中的对类级别的方法如:hasGetter()都是通过MetaClass操作的 对对象级别方法如:getValue是通过与ObjectWrapper配合实现的

关系一览

最新回复(0)