在日志模块中有BaseJdbcLogger、ConnectionLogger、PreparedStatementLogger、ResultSetLogger、StatementLogger通过动态代理的方式打印在不同的位置打印日志。几个相关的类图如下:
- BaseJdbcLogger是所有日志的增强类,用于记录jdbc那些方法需要增强,保存运行期间的sql参数信息。
- ConnectionLogger负责打印连接信息和sql语句。对Connection做增强,如果是调用prepareStatement、prepareCall、createStatement的方法,打印要执行的sql语句并返回prepareStatement的代理对象,让prepareStatement也具备日志能力,打印参数。
- PreparedStatementLogger负责对 PrepareStatement 对象增强,增强如下:
- 增强 PreparedStatement 的 setxxx 方法将参数设置到 columnMap、columnNames、columnValues,为打印参数做好准备。
- 增强PreparedStatement的executexxx方法,当执行时打印日志。
- 如果是查询,则增强resultSet方法,当返回值时,打印返回数据。如果是更新,增强getUpdateCount方法,打印被修改更新的行数,并返回更新行数。
- ResultSetLogger负责打印结果集数据。
那么mybatis在哪里加入日志主体的呢?
在mybatis中,Executor是访问数据库的组件,日志功能是在Executor中嵌入的,org.apache.ibatis.executor.SimpleExecutor类的prepareStatement方法
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Statement stmt;
Connection connection = getConnection(statementLog);
stmt = handler.prepare(connection, transaction.getTimeout());
handler.parameterize(stmt);
return stmt;
}