MyBatis 分为三层架构,分别是基础支撑层、核心处理层和接口层,如下图所示:
MyBatis 提供了日志模块来集成 Java 生态中的第三方日志框架,该模块目前可以集成 Log4j、Log4j2、slf4j 等优秀的日志框架。
MyBatis 的反射工具箱是在 Java 反射的基础之上进行的一层封装,为上层使用方提供更加灵活、方便的 API 接口,同时缓存 Java 的原生反射相关的元数据,提升了反射代码执行的效率,优化了反射操作的性能。
通过 SqlSession 获取 Mapper 接口的代理,然后通过这个代理执行关联 Mapper.xml 文件中的数据库操作。通过这种方式,可以将一些错误提前到编译期,该功能就是通过 Binding 模块完成的。
持久层框架核心组件之一就是数据源,MyBatis 自身提供了一套不错的数据源实现,也是 MyBatis 的默认实现。MyBatis 的数据源模块中也提供了与第三方数据源集成的相关接口,这也为用户提供了更多的选择空间,提升了数据源切换的灵活性。
数据库是实践生成中非常核心的存储,数据库性能的优劣直接影响了上层业务系统的优劣。
很多线上业务都是读多写少的场景,在数据库遇到瓶颈时,缓存是最有效、最常用的手段之一(如下图所示),正确使用缓存可以将一部分数据库请求拦截在缓存这一层,这就能够减少一部分数据库的压力,提高系统性能。
MyBatis 就提供了一级缓存和二级缓存,具体实现位于基础支撑层的缓存模块中。
mybatis-config.xml 配置文件和 Mapper.xml 配置文件的解析。
持久层框架一般都会提供一套事务管理机制实现数据库的事务控制,MyBatis 对数据库中的事务进行了一层简单的抽象,提供了简单易用的事务接口和实现。一般情况下,Java 项目都会集成 Spring,并由 Spring 框架管理事务。
核心处理层是 MyBatis 核心实现所在,其中涉及 MyBatis 的初始化以及执行一条 SQL 语句的全流程。
MyBatis 有三处可以添加配置信息的地方,分别是:mybatis-config.xml 配置文件、Mapper.xml 配置文件以及 Mapper 接口中的注解信息。在 MyBatis 初始化过程中,会加载这些配置信息,并将解析之后得到的配置对象保存到 Configuration 对象中。
MyBatis 的最大亮点应该要数其动态 SQL 功能了,只需要通过 MyBatis 提供的标签即可根据实际的运行条件动态生成实际执行的 SQL 语句。MyBatis 提供的动态 SQL 标签非常丰富,包括
**MyBatis 中的 scripting 模块就是负责动态生成 SQL 的核心模块。**它会根据运行时用户传入的实参,解析动态 SQL 中的标签,并形成 SQL 模板,然后处理 SQL 模板中的占位符,用运行时的实参填充占位符,得到数据库真正可执行的 SQL 语句。
要执行一条 SQL 语句,会涉及非常多的组件,比较核心的有:Executor、StatementHandler、ParameterHandler 和 ResultSetHandler。
其中,Executor 会调用事务管理模块实现事务的相关控制,同时会通过缓存模块管理一级缓存和二级缓存。SQL 语句的真正执行将会由 StatementHandler 实现。StatementHandler 会先依赖 ParameterHandler 进行 SQL 模板的实参绑定,然后由 java.sql.Statement 对象将 SQL 语句以及绑定好的实参传到数据库执行,从数据库中拿到 ResultSet,最后,由 ResultSetHandler 将 ResultSet 映射成 Java 对象返回给调用方,这就是 SQL 执行模块的核心。
很多成熟的开源框架,都会以各种方式提供扩展能力。当框架原生能力不能满足某些场景的时候,就可以针对这些场景实现一些插件来满足需求,这样的框架才能有足够的生命力。这也是 MyBatis 插件接口存在的意义。
**接口层是 MyBatis 暴露给调用的接口集合,**这些接口都是使用 MyBatis 时最常用的一些接口,例如,SqlSession 接口、SqlSessionFactory 接口等。其中,最核心的是 SqlSession 接口,你可以通过它实现很多功能,例如,获取 Mapper 代理、执行 SQL 语句、控制事务开关等。