1. 整体架构
123
2. 日志模块
日志模块需要解决 3 个问题:
- MyBatis 没有自己的日志实现,使用的是第三方日志组件。第三方日志组件日记级别各不相同,MyBatis 统一提供了 trace、debug、warn、error 4 个日志级别,这是如何做到的?
- MyBatis 是如何自动发现第三方日志实现的?
- MyBatis 是如何把日志优雅的嵌入到 JDBC 主体流程中?
2.1 统一日志级别
也就是解决第一个问题。
使用了适配器模式。
Log 统一日志级别:
以 Log4jImpl 为例,自己封装 Log4J 的实现,使用了 Log4J 的日志级别。
2.2 加载第三方日志实现
按照 Slf4J、CommonsLog、Log4J、Log4J、JdkLog、noLog 的顺序发现,并且是在调用 LogFactory.getLog 时发现的。
以加载 Slf4J 为例。
2.3 日志嵌入 JDBC 主体流程
使用了代理模式,具体使用的是动态代理,3 个动态代理类:ConnectionLogger、PreparedStatementLogger、ResultSetLogger。
在 JDBC 主体流程中,MyBatis 在下面 3 个地方嵌入了日志:
- SQL 语句
- SQL 语句中 ? 代表的参数
- SQL 执行结果
在 org.apache.ibatis.executor.SimpleExecutor.prepareStatement(StatementHandler, Log) 中:
- 创建 Connection,并使用 ConnectionLogger 进行了增强。
- 在 ConnectionLogger 的增强逻辑中打印 SQL 语句,创建 PreparedStatement,并使用 PreparedStatementLogger 对 PreparedStatement 进行了增强。
- 在 PreparedStatementLogger 中打印参数,执行 SQL,创建 ResultSet,并使用 ResultSetLogger 对 ResultSet 进行了增强。
- 在 ResultSetLogger 的增强中打印结果日志。
3. 数据源模块
需要解决 2 个问题:
- 如何创建一个连接
- 池化技术如何实现
3.1 创建一个数据库连接
使用工厂模式创建数据库连接。
- UnpooledDataSourceFactory、UnpooledDataSource
- PooledDataSourceFactory、PooledDataSource