MyBatis 源码解读(四)引入日志工具

loadCustomLogImpl 引入日志工具

解析配置使用的日志系统
XMLConfigBuilder.loadCustomLogImpl(settings);

首先在 mybatis-config.xml 中加入如下配置

<configuration>
    <settings>
        <setting name="logImpl" value="SLF4J" />
    </settings>
</configuration>

这里指定日志工具为 SLF4J 实现,接下来要跟踪下代码具体看看日志工具是如何被指定的。

private void loadCustomLogImpl(Properties props) {
  Class<? extends Log> logImpl = resolveClass(props.getProperty("logImpl"));
  configuration.setLogImpl(logImpl);
}

通过resolveClass 方法,根据我们传入的参数找到对应的 Class,其最终实现如下

public <T> Class<T> resolveAlias(String string) {
  try {
    if (string == null) { eturn null; }
    
    String key = string.toLowerCase(Locale.ENGLISH);
    Class<T> value;
    if (typeAliases.containsKey(key)) {
      value = (Class<T>) typeAliases.get(key);
    } else {
      value = (Class<T>) Resources.classForName(string);
    }
    return value;
  } catch (ClassNotFoundException e) {}
}

这里如果系统中已经注册了对应的常用类,则使用系统注册的值,否则,使用自自定义的值进行处理。因此,这里填写 SLF4J 和 填写 org.apache.ibatis.logging.slf4j.Slf4jImpl 是等价效果。

查看一下系统中默认已经注册了哪些值。
typeAliasRegistry 是在Configuration 构造方法中进行的初始化

public Configuration() {
  ......
  typeAliasRegistry.registerAlias("SLF4J", Slf4jImpl.class);
  typeAliasRegistry.registerAlias("COMMONS_LOGGING", JakartaCommonsLoggingImpl.class);
  typeAliasRegistry.registerAlias("LOG4J", Log4jImpl.class);
  typeAliasRegistry.registerAlias("LOG4J2", Log4j2Impl.class);
  typeAliasRegistry.registerAlias("JDK_LOGGING", Jdk14LoggingImpl.class);
  typeAliasRegistry.registerAlias("STDOUT_LOGGING", StdOutImpl.class);
  typeAliasRegistry.registerAlias("NO_LOGGING", NoLoggingImpl.class);
  ......
}

可以看到这里注册了 SLF4JCOMMONS_LOGGINGLOG4J LOG4J2JDK_LOGGINGSTDOUT_LOGGINGNO_LOGGING 七中方式其中前中是我们常用的日志工具,第六种表示是 System.out.println() 进行标准输出,第七种表示不使用日志。

在找到对应的Class 后 调用 configuration.setLogImpl(logImpl);方法设置为我们自定义的类,跟踪此方法,找到最后的实现为LogFactory.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) { }
}

这里最终将系统的日志构造器设置为我们自定义的日志工具的构造器(logConstructor = candidate;)。

如果没有指定日志系统,即没有配置 <setting name="logImpl" value="SLF4J" /> 属性,这个时候日志工厂类就会在系统中寻找默认的额日志工具:

static {
  // 这里默认的最高优先级使用的框架是SLF4J,笔者最推荐的也是这种方式。
  tryImplementation(LogFactory::useSlf4jLogging);
  tryImplementation(LogFactory::useCommonsLogging);
  tryImplementation(LogFactory::useLog4J2Logging);
  tryImplementation(LogFactory::useLog4JLogging);
  tryImplementation(LogFactory::useJdkLogging);
  tryImplementation(LogFactory::useNoLogging);
}
......
private static void tryImplementation(Runnable runnable) {
  if (logConstructor == null) {
    try {
      runnable.run();
    } catch (Throwable t) { }
  }
}

系统会按照优先级依次查找 SLF4JCOMMONS_LOGGINGLOG4JLOG4J2JDK_LOGGINGNO_LOGGING 是否有对应的日志实现,就是说在使用这几种日志系统的情况下,可以不用显式声明我们使用的日志框架。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值