Mybatis源码研究之Logger

1. Setting相关配置

<settings>
   <setting name="callSettersOnNulls" value="true"/>
    
    <setting name="logImpl" value="SLF4J" />
    
    
    <setting name="logPrefix" value="org.apache.ibatis." />
settings>

细节解释

MappedStatement.Builder类的构造函数中有这样一组代码:

String logId = id;
// 每个mappedStatement有自己专用的Log
// 而每个Log在获取时, 会加入我们自定义的log前缀(LogPrefix)
if (configuration.getLogPrefix() != null) {
    logId = configuration.getLogPrefix() + id;
}
// 设置本次执行时相关的Log
mappedStatement.statementLog = LogFactory.getLog(logId);    

2. org.apache.ibatis.logging

本package实现了对执行数据库操作时的日志记录

  1. 日志相关的package.提供了与各类logging框架进行适配的接口.
  2. 将自身的org.apache.ibatis.logging.Log接口适配出去.
  3. 参见org.apache.ibatis.logging.LogFactory类的setImplementation(Class implClass)私有静态方法.

3. org.apache.ibatis.logging.LogFactory

  1. LogFactory的静态构造块中,使用Runable接口非阻塞式地尝试访问classpath路径下的各种当前流程的log类库
  2. 从而为内部静态变量logConstructor赋值,所以在静态构造块中的调用顺序就决定了变量logConstructor的值(因为tryImplementation方法中会首先判断logConstructor是否为null,不为null才会去尝试加载其它的日志框架)
  3. 依次顺序为: Slf4j - JCL(Jakarta Commons Logging) - Log4j - Jdk14Logging - StdOut - NoLogging

4. org.apache.ibatis.logging.jdbc

  1. 具体负责Mybatis中日志信息的打印.
  2. 除了一个基类BaseJdbcLogger之外(官方注释: Base class for proxies to do logging), 其它的都是继承自该基类的子类,且都实现了InvocationHandler接口,切都有public static 方法newInstance,参数都一致(这里说的是一致,而不是相同); 即:

    1. `ConnectionLogger`         // 内部一个 `Connection` 类型字段
    2. `PreparedStatementLogger`  // 内部一个 `PreparedStatement` 类型字段  
    3. `ResultSetLogger`          // 内部一个 `ResultSet` 类型字段  
    4. `StatementLogger`          // 内部一个 `Statement` 类型字段  
    1. 以上Logger所针对的类型都是JDK的java.sql包下的原生类型(Connection, PreparedStatement, ResultSet, Statement).
    2. 这四个Logger都实现了InvocationHandler接口,所以很明显: MyBatis使用AOP来实现了日志功能.
    3. 这四个Logger都自定义了一个public static 方法newInstance,参数都一致(这里说的是一致,而不是相同);作用根据用户是否选择日志记录来进行代理.
    4. 例如: ” ==> Parameters: ” 位于 PreparedStatementLogger 类中的 44 行

5. 实例化的时机

  1. BaseExecutor类中的 getConnection方法里调用 ConnectionLogger.newInstance
  2. ConnectionLogger类中的invoke方法调用PreparedStatementLogger.newInstanceStatementLogger.newInstance.
  3. PreparedStatementLogger中的invoke方法和StatementLogger中的invoke方法调用ResultSetLogger.newInstance.

6. 总结

  1. Mybatis通过在配置文件中引入名为logPrefix的setting, 来允许框架使用者有权决定所使用的Logger, 进而达到复用框架使用者既有Logger的目的. 这种思路值得借鉴!

    \"logPrefix" value="org.apache.ibatis." />
  2. MyBatis使用AOP来实现了日志功能.
  1. Mybatis输出日志

你可能感兴趣的:(MyBatis3)