Mybatis 框架日志相关源码分析(二)

技术 · 2023-04-18

通过上篇文章《Mybatis 框架日志相关源码分析(一)》了解了 Mybatis 框架通过适配器模式,来整合其它日志框架。而我们都知道要想使用 Log 接口,就需要有具体的实现类对象,那么 Mybatis 是如何创建具体的实现类对象呢?

本文将分析 Mybatis 框架的日志相关源码,了解 Mybatis 如何创建日志实现类对象。

Mybatis 在解析到配置中的具体日志 Value 内容时,不仅保存了对应的 Class<? extends Log> 属性,还有一行代码:LogFactory.useCustomLogging(this.logImpl)

public void setLogImpl(Class<? extends Log> logImpl) {
  if (logImpl != null) {
    this.logImpl = logImpl;
    LogFactory.useCustomLogging(this.logImpl);
  }
}

LogFactory 这个类可谓是见名知意,Log 工厂,在设计模式中,这明显就是工厂模式。继续深入看看,这个工厂里面到底是如何创建对象的。首先从入口方法 useCustomLogging 看起,此方法代码很简单,直接调用了 setImplementation()

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);
  }
}

此方法的形参,对应的就是实现类的 Class 对象,首先获取了 Class 对象构造器,此构造器是带有一个形参为 String.class 。接着就是输出一些日志,最后,将此构造器对象,保存为静态属性:logConstructor 。当有外部代码需要输出日志,通过调用 getLog 方法即可实现日志输出:

public static Log getLog(Class<?> clazz) {
  return getLog(clazz.getName());
}

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);
  }
}

至此,我们了解了 Mybatis 通过工厂模式创建日志适配类对象。其中 LogFactory 中保存的是日志适配类的构造器对象,通过调用 getLog 方法,此工厂才返回具体的实现类对象。

Java MyBatis
Theme Jasmine by Kent Liao