【MyBatis源码解读】之日志模块

  |   0 评论   |   346 浏览

注:本文源码版本为3.4.6

日志模块总览

imagepng
Log:是日志接口。
LogException:定义异常类。
LogFactory:日志工厂类,他的作用是用来判断使用哪个日志框架。
commons包:整合jcl框架。
jdk14包:整合jul框架。
log4j包:整合log4j框架。
log4j2包:整合log4j2框架。
nologging包:不整合日志。
slf4j包:整合slf4j框架。
stdout包:控制台输出日志。
jdbc包:记录JDBC语句日志。

框架整合

这些包里面的类,大部分都实现了Log接口。
NoLoggingImpl:实现方法里面什么都没做。
StdOutImpl:实现方法里面使用System.err.println(s);来输出日志。
Log4jImpl:实现方法里使用了org.apache.log4j.Logger类的log.log(FQCN, Level.ERROR, s, null);等输出日志。
Jdk14LoggingImpl:实现方法里使用java.util.logging.Logger类的log.log(Level.SEVERE, s);等来输出日志。
JakartaCommonsLoggingImpl:实现方法里使用了org.apache.commons.logging.Log类的log.debug(s);等方法来输出日志。
Log4j2LoggerImpl:实现方法里使用了org.apache.logging.log4j.Logger类的log.debug(MARKER, s);等方法来输出日志。
Log4j2AbstractLoggerImpl:实现方法里使用org.apache.logging.log4j.spi.ExtendedLoggerWrapper类的log.logIfEnabled(FQCN, Level.DEBUG, MARKER, new SimpleMessage(s), null);等方法来输出日志。
Log4j2Impl:是Log4j2AbstractLoggerImpl和Log4j2LoggerImpl的封装,可以通过传入类名来判断使用哪个类。
Slf4jLoggerImpl:实现方法里使用了org.slf4j.Logger类的log.debug(s);等方法来输出日志。
Slf4jLocationAwareLoggerImpl:实现方法里使用了org.slf4j.spi.LocationAwareLogger类的logger.log(MARKER, FQCN, LocationAwareLogger.TRACE_INT, s, null, null);等方法来输出日志。
Slf4jImpl:是Slf4jLoggerImpl和Slf4jLocationAwareLoggerImpl的整合,通过传入的类名来判断使用哪个类。

public Slf4jImpl(String clazz) {
  //根据类名获取Logger对象
  Logger logger = LoggerFactory.getLogger(clazz);
  //如果Logger是LocationAwareLogger接口的实现类
  if (logger instanceof LocationAwareLogger) {
    try {
      // check for slf4j >= 1.6 method signature
 //检查slf4j版本是否大于等于1.6  
 logger.getClass().getMethod("log", Marker.class, String.class, int.class, String.class, Object[].class, Throwable.class);
  //满足要求就返回Slf4jLocationAwareLoggerImpl
  log = new Slf4jLocationAwareLoggerImpl((LocationAwareLogger) logger);
 return;  } catch (SecurityException e) {
      // fail-back to Slf4jLoggerImpl
  } catch (NoSuchMethodException e) {
      // fail-back to Slf4jLoggerImpl
  }
  }
  // Logger is not LocationAwareLogger or slf4j version < 1.6
 //如果版本小于1.6或者不是LocationAwareLogger的实现类,那么使用Slf4jLoggerImpl  
 log = new Slf4jLoggerImpl(logger);
}

LogFactory类

定义了MARKER为MYBATIS,有些日志框架需要使用该参数,如slf4j、log4j2。
getLog(Class<?> aClass)与getLog(String logger) 用来获取Log对象。
使用方式:

Log log =  LogFactory.getLog(DefaultVFS.class);

在LogFactory里面,首先会通过线程尝试每个日志框架,只要找到其中一个,就会把值赋值给logConstructor,找到之后就不再继续查找。
LogFactory类中提供了很多useXXX的方法,表示使用哪个框架。最核心的方法是:

private static void setImplementation(Class<? extends Log> implClass) {
  try {
    //生成字符串类型的构造器
    Constructor<? extends Log> candidate = implClass.getConstructor(String.class);
    //获取Log对象,输出一下日志
    Log log = candidate.newInstance(LogFactory.class.getName());
    if (log.isDebugEnabled()) {
      log.debug("Logging initialized using '" + implClass + "' adapter.");
    }
    //赋值
    logConstructor = candidate;
  } catch (Throwable t) {
    throw new LogException("Error setting Log implementation.  Cause: " + t, t);
  }
}

该方法就是用来获取具体使用哪个日志框架。

jdbc日志

当把mybatis设置了debug,那么会输出mybatis的一些执行语句。
imagepng
如,只有debug的时候才会输出日志。
imagepng

也可以关注我的公众号:程序之声

关注公众号,领取更多资源

本文为博主原创文章,未经博主允许不得转载。

评论

发表评论