mybatis源码——日志ErrorContext类

Posted chendeming

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mybatis源码——日志ErrorContext类相关的知识,希望对你有一定的参考价值。

一、特性表示

  mybatis的日志输出具有如下特性:

  (1)日志量随程序执行量增加(例如:xml文件中sql报错,那么一定会有初始化、xml加载等信息出现);

  (2)日志输出的顺序,是按顺序且隔离的;

 

二、附上源代码

 

package org.apache.ibatis.executor;

/**
 * @author Clinton Begin
 */
public class ErrorContext {

  private static final String LINE_SEPARATOR = System.getProperty("line.separator","
");
  private static final ThreadLocal<ErrorContext> LOCAL = new ThreadLocal<ErrorContext>();

  //暂存线程上下文
  private ErrorContext stored;

  private String sql;
  ... //各个阶段的值存储

  private Throwable cause;

  private ErrorContext() {
  }

  public static ErrorContext instance() {
    //单例模式,从当前线程获取线程存储变量(一个)
    ErrorContext context = LOCAL.get();
    if (context == null) {
      context = new ErrorContext();
      LOCAL.set(context);
    }
    return context;
  }

  public ErrorContext store() {
    stored = this;
    LOCAL.set(new ErrorContext());
    return LOCAL.get();
  }

  public ErrorContext recall() {
    if (stored != null) {
      LOCAL.set(stored);
      stored = null;
    }
    return LOCAL.get();
  }

  public ErrorContext sql(String sql) {
    //这种写法是流式编程
    this.sql = sql;
    return this;
  }

  public ErrorContext cause(Throwable cause) {
    this.cause = cause;
    return this;
  }

  public ErrorContext reset() {
    ...各个阶段记录初始化
    sql = null;
    
    LOCAL.remove();
    return this;
  }

  @Override
  public String toString() {
    StringBuilder description = new StringBuilder();

    ...各阶段日志输出

    // sql
    if (sql != null) {
      description.append(LINE_SEPARATOR);
      description.append("### SQL: ");
      description.append(sql.replace(‘
‘, ‘ ‘).replace(‘
‘, ‘ ‘).replace(‘	‘, ‘ ‘).trim());
    }

    // cause
    if (cause != null) {
      description.append(LINE_SEPARATOR);
      description.append("### Cause: ");
      description.append(cause.toString());
    }

    return description.toString();
  }

}

  

此处有几个值得借鉴的地方:

(1)使用ThreadLocal<ErrorContext>类变量可以做到在当前线程执行的任何阶段保证只有一个类对象实例。即使说,只要是出于一个线程,不论走多少层方法栈都没关系,只要使用对应方法将对应阶段的信息记录下来,最终在所有操作完结的使用toString()一下就能将整个过程的信息输出出来。(否则就要将信息存储的类一个接一个方法地以形参方式传入)

(2)每个记录方法都以类对象this返回,可以使用流式编程。简洁明了,可以直接将方法名.出来

以上是关于mybatis源码——日志ErrorContext类的主要内容,如果未能解决你的问题,请参考以下文章

#yyds干货盘点# mybatis源码解读:executor包(错误上下文)

MyBatis 源码篇-日志模块2

MyBatis源码解析之日志记录

mybatis 打印sql日志

mybatis 源码分析--日志分析

Mybatis 源码学习(11)-日志模块