(/≧▽≦)/~┴┴ 嗨~我叫小奥 ✨✨✨
👀👀👀 个人博客:小奥的博客
👍👍👍:个人CSDN
⭐️⭐️⭐️:传送门
🍹 本人24应届生一枚,技术和水平有限,如果文章中有不正确的内容,欢迎多多指正!
📜 欢迎点赞收藏关注哟! ❤️
一、mybatis整体架构
本博文主要是分享自己学习MyBatis源码的一些记录,会参考大量的博文和一些书籍,链接会放在文末。
MyBatis版本:3.5.14
下载源来自Github,fork到自己仓库中,然后clone即可。
1.1 项目结构
如下图,是MyBatis源码的目录结构下的所有包。
其中,各个包的内容简介如下:
包名称 | 包内内容简介 |
---|---|
annotation | 注解目录。包括所有的注解。如@SELECT ,@UPDATE 等 |
binding | Mapper类的实例反射生成工具目录 |
builder | 主要是注解,mapper和SqlSuorce的构造器及转换器 |
cache | Mybatis内部缓存接口。实现了一些特定的缓存策略。FifoCache ,LruCache ,BlockingCache ,LoggingCache 等 |
cursor | 默认的游标处理类 |
dataSource | 数据源工厂类及实现。实现类包括JndiDataSourceFactory 、PooledDataSourceFactory 、UnpooledDataSourceFactory 。 数据源实现类: UnpooledDataSource 、PooledDataSource
|
exceptions | Mybatis自定义的三个异常类。ExceptionFactory 、PersistenceException 、TooManyResultsException 、IbatisException 。都继承自RuntimeException
|
executor | 执行器相关包。包括Key生成器、加载器(包括Cglib、Javassist的代理,结果加载器)、参数处理器接口、结果处理器、结果集(resultSet)处理器、Statement处理器(实现类:BaseStatementHandler 、CallableStatementHandler 、PreparedStatementHandler 、RoutingStatementHandler 、SimpleStatementHandler )、执行器(SimpleExecutor 、ReuseExecutor 、CachingExecutor 、BatchExecutor 、BaseExecutor ) |
io | 主要是定义的几个VFS(VFS 、DefaultVFS 、ClassLoaderWrapper ) |
jdbc | 与Sql相关的操作。如Sql运行器,脚本运行器和Sql封装类等 |
lang | 指定是用java7还是java8的API的注解.UsesJava7 、UsesJava8
|
logging | 各个类型的日志适配器,都实现了Log 接口。StdOutImpl 、Slf4jImpl 、NoLoggingImpl 、Log4j2Impl 、Log4jImpl 、Jdk14LoggingImpl 、BaseJdbcLogger 、Jakarta***monsLoggingImpl
|
mapping | 主要是接口参数,sql和返回结果的映射类,主要类包括:MappedStatement ,ParameterMap ,ParameterMapping ,ResultMap ,ResultMapping ,BoundSql ,SqlSource 等类 |
parsing | 变量解析.如解析${} ,#{} 等 |
plugin | 主要包含插件的定义接口。如Interceptor ,Plugin ,InterceptorChain 等 |
reflection | 主要是一些反射操作的工具方法和对象工厂类,以及一些常用的包装类,如BaseWrapper ,BeanWrapper ,CollectionWrapper ,MapWrapper ,ObjectWrapper 。 |
scripting | 执行驱动和动态Sql解析 |
session | 主要是SqlSession和SqlSessionFactory |
transaction | 主要是mybatis简单封装的jdbc事务操作类 |
type | 各个类型数据的处理器。用于动态的设置参数和转换数据。如IntegerTypeHandler 用来处理Integer类型的值的set和get操作。除了八大基本类型。还有常用的集合及Map类型,还增加了各种时间类型的处理器 |
2 整体架构
MyBatis的整体架构分为三层:基础支持层、核心处理层和接口层。
(1)基础支持层
基础支持层,包含整个 MyBatis 的基础模块,这些模块为核心处理层的功能提供了良好的支撑
- 反射模块:对 Java 原生的反射进行良好的封装,进行了一系列的优化,提供更加简洁易用的 API 方便使用。并且对反射操作进行了一系列优化,例如缓存了类的元数据,提高反射操作的性能
- 类型转换模块:类型转换模块主要提供了两个主要功能,一个是别名机制,MyBatis为了简化配置文件提供了别名机制;另一个功能是实现JDBC类型与Java类型之间的转化,该功能在为SQL语句绑定实参以及映射查询结果集时都会涉及
- 日志模块:提供日志输出,支持集成第三方日志框架
- 资源加载模块:主要是对类加载器进行封装,确定类加载器的使用顺序,并提供了加载类文件以及其他资源文件的功能
- 解析器模块:主要提供两个功能,一个是对XPath的封装,为MyBatis初始化时解析mybatis-config.xml配置文件以及映射配置文件提供支持;另一个功能是为处理动态SQL语句中的占位符提供支持
- 数据源模块:提供相应的 DataSource 数据源实现,支持与第三方数据源的继承
- 事务模块:对数据库中的事务进行了抽象,提供事务接口的简单实现
- 缓存模块:提供一级缓存和二级缓存的支持
- Binding 模块:提供 Mapper 接口与 XML 映射文件进行关联的支持
- 异常模块:定义 MyBatis 自己的 Exception
- 注解模块:提供MyBatis相关注解支持
(2)核心处理层
核心处理层实现了MyBatis的核心处理流程,其中包括MyBatis的初始化以及完成一次数据库操作涉及的全部流程。
① 配置解析
在 MyBatis 初始化过程中,会加载 mybatis-config.xml 配置文件、映射配置文件以及 Mapper 接口中的注解信息,解析后的配置信息会形成相应的对象并保存到 Configuration 对象中。之后,利用该 Configuration 对象创建 SqlSessionFactory 对象。待 MyBatis 初始化之后,开发人员可以通过初始化得到 SqlSessionFactory 创建 SqlSession 对象并完成数据库操作。
② SQL解析和scripting模块
MyBatis实现动态SQL功能,提供了多种动态SQL语句对应的节点。如<where>
、<if>
等节点,通过这些节点的组合使用,开发人员可以写出几乎满足所有需求的动态SQL语句。
MyBatis 中的 scripting 模块会根据用户传入的实参,解析映射文件中定义的动态 SQL 节点,并形成数据库可执行的 SQL 语句。之后会处理 SQL 语句中的占位符,绑定用户传入的实参。
③ SQL执行
SQL 语句的执行涉及多个组件,其中比较重要的是 Executor
、StatementHandler
、ParameterHandler
和 ResultSetHandler
。
Executor 主要负责维护一级缓存和二级缓存,并提供事务管理的相关操作,它会将数据库相关操作委托给StatementHandler 完成。StatementHandler 首先通过 ParameterHandler 完成 SQL 语句的实参绑定;然后通过 java.sql.Statement 对象执行 SQL 语句并得到结果集;最后通过 ResultSetHandler 完成结果集的映射,得到结果对象并返回。
④ 插件
用户可以通过添加自定义插件的方式对 MyBatis 进行扩展。用户自定义插件也可以改变 MyBatis 的默认行为,例如,我们可以拦截 SQL 语句并对其进行重写。由于用户自定义插件会影响 MyBatis 的核心行为,在使用自定义插件之前,开发人员需要了解 MyBatis 内部的原理,这样才能编写出安全、高效的插件。
下图展示了MyBatis执行一条SQL语句的大致过程:
(3)接口层
接口层相对简单,其核心是SqlSession接口,该接口中定义了MyBatis暴露给应用程序调用的Api,也就是上层应用与MyBatis交互的桥梁。接口层在收到调用请求时,会调用核心处理层的相应模块来完成具体的数据库操作。
(4)总结
MyBatis的代码并不是很多,相对于源码阅读入门的同学来说还是比较简单的,我会按照以上三个模块(基础支持层 ==> 核心处理层 ==> 接口层)进行逐步分析。