Mybatis中Logging模块的源码分析

周末又来到了公司吹吹空调,顺便记录下Mybatis的点点滴滴。

首先Mybatis不定义日志系统,完全依赖于第三方系统完成日志记录,利用适配器模式完成实际操作,源码如下:

 1:定义一个Log接口,具有如下方法:

public interface Log {

  boolean isDebugEnabled();

  boolean isTraceEnabled();

  void error(String s, Throwable e);

  void error(String s);

  void debug(String s);

  void trace(String s);

  void warn(String s);
}

2 :然后引入第三方日志,比如XXXLoggingImpl,实现Log接口,然后用第三方的log去完成真实的动作,如下:

public class Log4jImpl implements Log {
  
  private static final String FQCN = Log4jImpl.class.getName();

  private final Logger log;

  public Log4jImpl(String clazz) {
    log = Logger.getLogger(clazz);
  }

  @Override
  public boolean isDebugEnabled() {
    return log.isDebugEnabled();
  }

  @Override
  public boolean isTraceEnabled() {
    return log.isTraceEnabled();
  }

  @Override
  public void error(String s, Throwable e) {
    log.log(FQCN, Level.ERROR, s, e);
  }

  @Override
  public void error(String s) {
    log.log(FQCN, Level.ERROR, s, null);
  }

  @Override
  public void debug(String s) {
    log.log(FQCN, Level.DEBUG, s, null);
  }

  @Override
  public void trace(String s) {
    log.log(FQCN, Level.TRACE, s, null);
  }

  @Override
  public void warn(String s) {
    log.log(FQCN, Level.WARN, s, null);
  }

这样的实现类有JakartaCommonsLoggingImpl,Jdk14LoggingImpl,Log4j2AbstractLoggerImpl,NoLoggingImpl,Slf4jImpl,StdOutImpl等,那么问题来了,这些实现类是如何被Mybatis引用的呢?

3 面就是本文的重点LogFactory,LogFactory有个静态的类变量,也就是真正完成日志记录类的构造方法,还有静态代码块,其中完成的动作比较清晰,就是依次完成
实例化各个日志类,如果系统包含对应的日志模块,则反射实例化成功,然后将构造方法时设置为该类的构造方法,如果失败的话,依次尝试下一个,直到最后无日志记录。

Constructor<? extends Log> logConstructor;

 private static void setImplementation(Class<? extends Log> implClass) {
    try {
      Constructor<? extends Log> candidate = implClass.getConstructor(String.class);
      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);
    }
  }

static {
    tryImplementation(new Runnable() {
      @Override
      public void run() {
        useSlf4jLogging();
      }
    });
.......

  LogFactory有个静态方法,获得Log的实现类,然后在项目中引用。

public static Log getLog(String logger) {
    try {
      return logConstructor.newInstance(logger);
    } catch (Throwable t) {
      throw new LogException("Error creating logger for logger " + logger + ".  Cause: " + t, t);
    }
  }

猜你喜欢

转载自blog.csdn.net/qq_21190979/article/details/81411234