该系列文章针对 Mybatis 3.5.1 版本
MyBatis 在设置预处理语句(PreparedStatement)中的参数或从结果集中取出一个值时, 都会用typeHandler类型处理器将获取到的值以合适的方式转换成 Java 类型,或者将 Java 类型映射成数据库支持的类型。
在 Mybatis 中内置了很多的 TypeHandler ,这些内置的 TypeHandler 存储在了 TypeHandlerRegistry 容器中。
如下图,在 TypeHandlerRegistry 构造函数中,初始化了几乎所有使用类型的TypeHandler
在 Mybatis 中除了内置的 TypeHandler ,Mybaits 允许自定义 TypeHandler 并将其注册到 TypeHandlerRegistry 容器中。
TypeHandlerRegistry 容器会以属性值的方式,存在于 Configuration 对象中。
自定义 TypeHandler 相关配置信息配置在 mybatis-config.xml 中的 <typeHandlers>标签下,配置的方式有两种
1、通过 <package> 配置 多个 typeHandler所在的包路径,通过扫包的方式批量设置
2、通过 <typeHandler> 标签,一个一个进行 typeHandler 配置
typeHandler 在 mybaits-config.xml 配置案例如下:
回顾下XMLConfigBuilder 解析时序图
如图,<typeHandler> 标签的解析代码在 XMLConfigBuilder#typeHandlerElement 中,具体解析代码如下:
在上述代码中主要分别对两种 typeHandler 配置方式进行解析。
XMLConfigBuilder 借助 XPathParser 进行标签数据解析,根据获取到的解析内容调用 TypeHandlerRegistry 的注册方法,进行 TypeHandler 的注册操作。
所以 XMLConfigBuilder 针对标签 <typeHandlers> 及其子标签只是进行单纯的数据组装,解析由 XPathParser 完成,存储则由 TypeHandlerRegistry 完成。
然后再把 TypeHandlerRegistry 作为属性值存储在 Configuration 对象中。 将所有的 typeHandler 信息存到了 TypeHandlerRegistry 中。
TypeHandlerRegistry 是一个容器,该容器是用来存放 Mybatis 运行期间所有的 TypeHandler 。
来看一下容器 TypeHandlerRegistry 是如何存放数据的,相关代码如下:
如上述代码,针对 TypeHandler 的存储基本上都是 key-value 的方式进行存储,使得同一个 TypeHandler 能够通过各种类型的 key 进行获取。
再来看一下,TypeHandlerRegistry 对外提供的注册方法
如图,注册的重载方法有点多,不过实现方式大同小异,这里来看一下关于包配置的注册逻辑,也就是 <typeHandlers> 下的子标签 <package> 配置的扫包注册操作。
代码如下:
上述代码进行 TypeHandler 注册主流程为:
1、根据包名获取 class 文件
2、ClassLoader 加载 class 文件,过滤出为 TypeHandler 实现类的 class 文件
3、对 class 在进行一次过滤,去除内部类、接口类、package-info.java 类
4、将过滤完后的类存储到 TypeHandlerRegistry 的容器中
上述代码还没有进行真正的注册操作,只是进行 TypeHandler 查找和过滤,具体具体流程可以自行查阅。
在加入了 TypeHandler 类型处理器后,Mybatis 整体的运行框架如下:
文章实时更新关注公众号