• Mybatis源码-详解Mybatis日志设计


    众所周知,Mybatis是在ORM领域,使用的较为广泛,而Mybatis日志体系,也是值得我们学习的地方,由于各个厂商都有自己的日志api,基于此,Mybatis对日志进行了封装,来适配各个厂商的日志

    1. 日志级别

    在Mybatis内部定义了4个级别:

    1. Error:错误
    2. warn:警告
    3. debug:调试
    4. trance:

    2. 日志优先级

    error>warn>debug>trance

    3. 源码解析

    接口

    org.apache.ibatis.logging.Log

    该接口定义了一系列的常用日志方法,便于日志打印

    /**
     * 日志相关接口
     * @author Clinton Begin
     */
    public interface Log {
      /**
       * 判断debug是否打开
       * @return
       */
      boolean isDebugEnabled();
    
      /**
       * 判断trance是否打开
       * @return
       */
      boolean isTraceEnabled();
    
      /**
       * 错误日志打印
       * @param s
       * @param e
       */
      void error(String s, Throwable e);
    
      void error(String s);
    
      /**
       * debug日志打印
       * @param s
       */
      void debug(String s);
    
      /**
       * trance日志打印
       * @param s
       */
      void trace(String s);
    
      /**
       * warn 日志打印
       * @param s
       */
      void warn(String s);
    
    }
    

    实现类:

    基于各个厂商的日志对Log有以下实现,都基本上是根据厂商日志,编写对应的适配器类来调用对应的日志系统

    日志集成核心类

    org.apache.ibatis.logging.LogFactory
    

    实现原理:

    1. 使用Static 方法在类进行初始化的时候去尝试加载对应的实现类
    2. 优先级为:slf4j>commonLog>log4j2>log4j>jdk>noLog
    3. 当获取到的实现类不为空时候则不进行加载了
    /**
     *    Copyright 2009-2020 the original author or authors.
     *
     *    Licensed under the Apache License, Version 2.0 (the "License");
     *    you may not use this file except in compliance with the License.
     *    You may obtain a copy of the License at
     *
     *       http://www.apache.org/licenses/LICENSE-2.0
     *
     *    Unless required by applicable law or agreed to in writing, software
     *    distributed under the License is distributed on an "AS IS" BASIS,
     *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     *    See the License for the specific language governing permissions and
     *    limitations under the License.
     */
    package org.apache.ibatis.logging;
    
    import java.lang.reflect.Constructor;
    
    /**
     * 日志工厂类
     * @author Clinton Begin
     * @author Eduardo Macarron
     */
    public final class LogFactory {
    
      /**
       * Marker to be used by logging implementations that support markers.
       */
      public static final String MARKER = "MYBATIS";
      /**
       * 日志系统构造函数
       */
      private static Constructor<? extends Log> logConstructor;
    
      static {
        //尝试加载实现类
        /**
         * slf4j>commonLog>log4j2>log4j>jdk>noLog
         */
        tryImplementation(LogFactory::useSlf4jLogging);
        tryImplementation(LogFactory::useCommonsLogging);
        tryImplementation(LogFactory::useLog4J2Logging);
        tryImplementation(LogFactory::useLog4JLogging);
        tryImplementation(LogFactory::useJdkLogging);
        tryImplementation(LogFactory::useNoLogging);
      }
    
      private LogFactory() {
        // disable construction
      }
    
      public static Log getLog(Class<?> clazz) {
        //获取日志打印
        return getLog(clazz.getName());
      }
    
      /**
       * 根据类名获取对应的日志实例
       * @param logger
       * @return
       */
      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);
        }
      }
    
      /**
       * 设置个性化日志
       * @param clazz
       */
      public static synchronized void useCustomLogging(Class<? extends Log> clazz) {
        setImplementation(clazz);
      }
    
      public static synchronized void useSlf4jLogging() {
        setImplementation(org.apache.ibatis.logging.slf4j.Slf4jImpl.class);
      }
    
      public static synchronized void useCommonsLogging() {
        setImplementation(org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl.class);
      }
    
      public static synchronized void useLog4JLogging() {
        setImplementation(org.apache.ibatis.logging.log4j.Log4jImpl.class);
      }
    
      public static synchronized void useLog4J2Logging() {
        setImplementation(org.apache.ibatis.logging.log4j2.Log4j2Impl.class);
      }
    
      public static synchronized void useJdkLogging() {
        setImplementation(org.apache.ibatis.logging.jdk14.Jdk14LoggingImpl.class);
      }
    
      public static synchronized void useStdOutLogging() {
        setImplementation(org.apache.ibatis.logging.stdout.StdOutImpl.class);
      }
    
      public static synchronized void useNoLogging() {
        setImplementation(org.apache.ibatis.logging.nologging.NoLoggingImpl.class);
      }
    
      /**
       * 尝试加载实现类
       * @param runnable
       */
      private static void tryImplementation(Runnable runnable) {
        if (logConstructor == null) {
          try {
            runnable.run();
          } catch (Throwable t) {
            // ignore
          }
        }
      }
    
      /**
       * 设置实现类方法
       * @param implClass
       */
      private static void setImplementation(Class<? extends Log> implClass) {
        try {
          //获取Log默认String 的构造参数
          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);
        }
      }
    
    }
    
    
  • 相关阅读:
    python函数名和左括号之间不能有空格
    linux版本选择
    filter_map
    awk统计总结
    Spring Boot + Redis 实现各种操作
    手机号正则校验
    判断windows系统
    Redis分布式锁
    shell 脚本快速部署 SpringBoot 项目
    Java主流的Http请求--原生的HttpURLConnection
  • 原文地址:https://www.cnblogs.com/lonecloud/p/14219184.html
Copyright © 2020-2023  润新知