注:该内容来源于《Mybatis技术内幕》一书。
MyBatis的整体架构分为三层, 分别是基础支持层、核心处理层和接口层。
基础支撑层主要包括了数据源模块、事务管理模块、缓存模块、Bingding模块、反射模块、类型转换、日志模块、资源加载、解析器模块等。
核心处理层主要包括了配置解析、参数映射、SQL解析、SQL执行、结果集映射、插件等模块。
10. 配置解析
在MyBatis初始化过程中,会加载mybatis-config.xml 配置文件、映射配置文件以及Mapper接口中的注解信息,解析后的配置信息会形成相应的对象并保存到Configuration 对象中。
11. SQL解析
拼凑SQL 语句是一件烦琐且易出错的过程,为了将开发人员从这项枯燥无趣的工作中解脱出来, MyBatis 实现动态SQL语句的功能,提供了多种动态SQL语句对应的节点,比如:
12. SQL执行
SQL 语句的执行涉及多个组件,其中比较重要的是Executor、StatementHandler、
ParameterHandler和ResultSetHandler。Executor 主要负责维护一级缓存和二级缓存,并提供事务管理的相关操作,它会将数据库相关操作委托给StatementHandler完成。StatementHandler首先通过ParameterHandler 完成SQL 语句的实参绑定,然后通过java.sql.Statement对象执行SQL语句并得到结果集,最后通过ResultSetHandler完成结果集的映射,得到结果对象并返回。
13. 插件
Mybatis 自身的功能虽然强大,但是并不能完美切合所有的应用场景,因此MyBatis提供了插件接口,我们可以通过添加用户自定义插件的方式对MyBati s 进行扩展。用户自定义插件也可以改变Mybatis 的默认行为,例如,我们可以拦截SQL 语句并对其进行重写。由于用户自定义插件会影响MyBatis 的核心行为,在使用自定义插件之前,开发人员需要了解MyBatis内部的原理,这样才能编写出安全、高效的插件。
接口层相对简单,其核心是SqlSession 接口,该接口中定义了MyBatis暴露给应用程序调用的API ,也就是上层应用与MyBatis交互的桥梁。接口层在接收到调用请求时,会调用核心处理层的相应模块来完成具体的数据库操作。
源码包机构如下图所示:
14. org.apache.ibatis.annotations包 (核心处理层—配置解析)
主要包含了所有mapper接口中用到的注解,比如常用的@Param、@Update、@Select、@Delete等。
15. org.apache.ibatis.binging包 (基础支撑层—Binding模块)
将mapper接口绑定配置Mapper语句。
16. org.apache.ibatis.builder包(核心处理层—配置解析)
实现配置对象(包括XML、注解)的构建,比如Configuration等。
17. org.apache.ibatis.cache包(基础支撑层—缓存模块)
缓存功能实现。包括各类装饰器等。
18. org.apache.ibatis.cursor包(核心处理层—SQL执行)
实现游标方式查询数据、游标适合处理大数据量的查询操作,通常情况下不适合一次性加载到内存中的这种查询方式。
19. org.apache.ibatis.datasource包(基础支撑层—数据源)
数据源相关类
20. org.apache.ibatis.exceptions包(基础基础层,异常基类)
Mybatis中异常类的基类。
21. org.apache.ibatis.executor包(核心处理层—SQL执行)
SQL语句执行器,核心包
22. org.apache.ibatis.io包(基础支撑层—资源加载)
资源文件读取
23. org.apache.ibatis.jdbc包(基础支撑层—数据源)
JDBC一些操作。
24. org.apache.ibatis.lang包(基础基础层,工具类)
这个包只有2个注解 @UsesJava7 @UsesJava8 使用这个两个注解标识哪些可以使用JDK7 API 哪些可以使用JDK8 API
25. org.apache.ibatis.logging包(基础支撑层—日志模块)
日志功能,实现各类日志框架的对接。
26. org.apache.ibatis.mapping包(核心处理层—参数映射、结果集映射等)
配置文件与实体对象的映射功能,比如:Mapper映射、参数映射、结果集映射等。
27. org.apache.ibatis.parsing包(基础支撑层—解析器模块)
解析工具包
28. org.apache.ibatis.plugin包(核心处理层—插件)
拦截器功能实现
29. org.apache.ibatis.reflection包(基础支撑层—反射模块)
反射器功能,这个包下实现了元数据编程。
30. org.apache.ibatis.scripting包(核心处理层—配置解析)
动态SQL语句实现。比如配置文件中的、等节点
31. org.apache.ibatis.session包(接口层)
主要实现SqlSession功能,核心包。
32. org.apache.ibatis.transaction包(基础支撑层—数据源)
事务功能实现
33. org.apache.ibatis.type包(基础支撑层—类型转换)
类型处理功能实现
结合上一篇《源码环境搭建》中的例子,分析Mybatis执行一次SQL语句的过程,大致如下:
@Override
public List doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
Statement stmt = null;
try {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
stmt = prepareStatement(handler, ms.getStatementLog());
return handler.query(stmt, resultHandler);
} finally {
closeStatement(stmt);
}
}
4、上一步中StatementHandler实例对象实际上就是RoutingStatementHandler实例对象。即实际执行了RoutingStatementHandler实例对象的query方法。该方法中又调用了PreparedStatementHandler对象中的query方法。代码如下:
@Override
public List query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
return resultSetHandler. handleResultSets(ps);
}
5、PreparedStatementHandler的query方法中实际上通过java.sql.PreparedStatement的execute方法,实现了数据库查询。然后查询结果集由resultSetHandler进行处理,并进行返回。结果集处理方法代码如下:
@Override
public List
总结,方法执行过程中,类和方法的调用顺序如下图所示: