Java数据持久层 (3)

SAX:SAX 是基于事件模型的XML 解析方式。当SAX 解析器解析到某类型节点时,会触发注册在该类型节点上的回调函数,开发人员可以根据自己感兴趣的事件注册相应的回调函数。由于在处理过程中井不会在内存中记录XML 中的数据,所以占用的资源比较小,这是其优点。其缺点是因为不存储XML 文挡的结构,所以需要开发人员自己负责维护业务逻辑涉及的多层节点之间的关系。

StAX:StAX将XML 文档作为一个事件流进行处理。不同于SAX,在StAX 解析方式中,应用程序控制着整个解析过程的推进,可以简化应用处理XML 文档的代码,并且决定何时停止解析,而且StAX 可以同时处理多个XML 文档。

而Mybatis则是采用DOM解析方式,并结合XPath进行XML解析。

DOM 会将整个XML 文档加载到内存中并形成树状数据结构,而XPath 是一种为查询XML 文档而设计的语言,可以与DOM 解析方式配合使用,实现对XML 文档的解析。XPath 之于XML 就好比SQL 语言之于数据库。

在这里插入图片描述

org.apache.ibatis.parsing.XPathParser#variables:mybatis-config.xml 中<propteries>标签定义的键位对集合。
XPathParser中提供了一系列的eval*方法用于解析boolean、short、long、int、String、Node等类型的信息,它通过调用XPath.evaluate方法查找指定路径的节点或属性,并进行相应的类型装换。
剩余部分,此处不再详解。

b.反射模块

Mybatis运行过程中,大量使用了反射(如生成DAO对应代理实现类)。Mybatis对Java原生的反射操作进行了进一步的封装,从而提供更加简洁的API。
Reflector 是MyBatis 中反射模块的基础,每个Reflector 对象都对应一个类,在Reflector 中缓存了反射操作需要使用的类的元信息。

在这里插入图片描述

从上图中,可以看出

核心类:

Reflector:对于每个类,都有一个对应的Reflector,用于保存其类元信息。可以类比Spring中的Bean。但是其内部没有类之间的关联&依赖关系

MetaClass:MetaClass 是MyBatis 对类级别的元信息的封装和处理。MetaClass 通过Reflector 和PropertyTokenizer 组合使用, 实现了对复杂的属性表达式的解析,并实现了获取指定属性描述信息的功能。

MetaObject:ObjectWrapper实现的属性表达式解析功能,是委托给MetaObject实现的。

包:

invoker:包含MethodInvoker、SetFieldInvoker等,用于实现目标方法反射调用,属性读取与设置等

factory:包含ObjectFactory&DefaultObjectFactory,对象创建工厂。ObjectFactory提供实例创建接口,其默认实现为DefaultObjectFactory。在Mybatis源码的测试类中,存在对应测试。

property:包含PropertyCopier、PropertyNamer、PropertyTokenizer,是类字段工具,提供如字段复制、字段是否为属性、字段与index转化(属性表达式&Sql占位符应用)等功能。

wrapper:包含ObjectWrapperFactory、ObjectWrapper、BaseWrapper等。ObjectWrapper接口是对对象的包装,抽象了对象的属性信息,定义了一系列查询对象属性信息的方法,以及更新属性的方法。

TypeParameterResolver:进行类型解析。如TypeParameterResolver#resolveReturnType会返回对应类&方法的返回类型。在Mybatis源码的测试类中,存在对应测试。

Reflector

每个类,都有其对应等Reflector,用于保存其对应的类元信息(属性,字段等)

public class Reflector { // 对应的Class 类型 private final Class<?> type; // 可读属性的名称集合 private final String[] readablePropertyNames; // 可写属性的名称集合 private final String[] writablePropertyNames; // 属性相应的setter方法,key是属性名称,value是Invoker对象 private final Map<String, Invoker> setMethods = new HashMap<>(); // 属性相应的getter方法集合,key是属性名称,value是Invoker对象 private final Map<String, Invoker> getMethods = new HashMap<>(); // 属性相应的setter方法的参数值类型,key是属性名称,value是setter方法的参数类型 private final Map<String, Class<?>> setTypes = new HashMap<>(); // 属性相应的getter方法的返回位类型,key是属性名称,value是getter方法的返回位类型 private final Map<String, Class<?>> getTypes = new HashMap<>(); // 默认构造方法 private Constructor<?> defaultConstructor; // 所有属性名称的集合,key是属性名称的大写形式,value是属性名称 private Map<String, String> caseInsensitivePropertyMap = new HashMap<>(); // 构造方法 public Reflector(Class<?> clazz) { type = clazz; addDefaultConstructor(clazz); addGetMethods(clazz); addSetMethods(clazz); addFields(clazz); // 学习一下:Collection.toArray()返回的是Object[],而Collection.toArray(T[] a)返回的是T[] readablePropertyNames = getMethods.keySet().toArray(new String[0]); writablePropertyNames = setMethods.keySet().toArray(new String[0]); for (String propName : readablePropertyNames) { caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName); } for (String propName : writablePropertyNames) { caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName); } } // 其他方法 }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsfjfp.html