mybatis的Log机制浅谈

官方说明:https://mybatis.org/mybatis-3/zh/logging.html

我们在使用Log时一般是这样定义Log的:Log log = LogFactory.getLog(class)。

mybatis也不例外,通过分析源码发现mybatis自己定义了Log和LogFactory,而没有采用我们通用的commons-logging或者slf4j-api。这样可以最少化对第三方日志框架的依赖性。

mybatis类之间的关系(工厂模式+状态模式)如下图所示:

mybatis的Log机制浅谈_第1张图片

从上图可以看出,它对不过是对org.slf4j、org.apache.commons.logging、org.apache.log4j、java.util.logging等六种Log框架的同时封装。

在加载LogFactory时,首先执行静态代码块,来决定使用何种日志框架。从代码中可以看到,采用日志框架是有先后顺序的。 

    static {  
        tryImplementation(new Runnable() {  
            public void run() {  
                useSlf4jLogging();  
            }  
        });  
        tryImplementation(new Runnable() {  
            public void run() {  
                useCommonsLogging();  
            }  
        });  
        tryImplementation(new Runnable() {  
            public void run() {  
                useLog4JLogging();  
            }  
        });  
        tryImplementation(new Runnable() {  
            public void run() {  
                useJdkLogging();  
            }  
        });  
        tryImplementation(new Runnable() {  
            public void run() {  
                useNoLogging();  
            }  
        });  
    }  
    private static void tryImplementation(Runnable runnable) {  
        if (logConstructor == null) {   
            try {  
                runnable.run(); // 不是启动新线程,而是普通的函数调用。  
            } catch (Throwable t) {  
                // ignore  
            }  
        }  
    }    
public static synchronized void useSlf4jLogging() {  
    setImplementation("org.apache.ibatis.logging.slf4j.Slf4jImpl");  
}  
  
public static synchronized void useCommonsLogging() {  
    setImplementation("org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl");  
}  
  
public static synchronized void useLog4JLogging() {  
    setImplementation("org.apache.ibatis.logging.log4j.Log4jImpl");  
}  
  
public static synchronized void useJdkLogging() {  
    setImplementation("org.apache.ibatis.logging.jdk14.Jdk14LoggingImpl");  
}  
  
public static synchronized void useStdOutLogging() {  
    setImplementation("org.apache.ibatis.logging.stdout.StdOutImpl");  
}  
  
public static synchronized void useNoLogging() {  
    setImplementation("org.apache.ibatis.logging.nologging.NoLoggingImpl");  
} 

 决定采用何种框架是在setImplementation函数中。如果没有抛出异常,则采用此种框架。

    private static void setImplementation(String implClassName) {  
        try {  
            @SuppressWarnings("unchecked")  
            Class implClass = (Class) Resources  
                    .classForName(implClassName);  // 查找实现类  
            Constructor candidate = implClass  
                    .getConstructor(new Class[] { Class.class });  
            Log log = candidate.newInstance(new Object[] { LogFactory.class });  
            log.debug("Logging initialized using '" + implClassName  
                    + "' adapter.");  
            logConstructor = candidate;  
        } catch (Throwable t) {  
            throw new LogException("Error setting Log implementation.  Cause: "  
                    + t, t);  
        }  
    }  

mybatis的logImpl可选值:

mybatis的Log机制浅谈_第2张图片

mybatis.configuration.logImpl属性官方说明:

logImpl 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING 未设置

你可能感兴趣的:(mybatis的Log机制浅谈)