说明
Mybatis框架,如果没有日志 jar 包,就不会打印日志,也不会报错
加上 日志 jar包(还要有相关配置文件),就会打印日志
这和我们使用的日志不同,我们使用日志时,必须有jar包,否则就会报错找不到类
Mybatis实现原理
Mybatis 的 logging 包下,都是跟日志相关的类
Log
是使用日志的接口,通过该接口打印日志
LogFactory
Log工厂,也是核心
加载日志框架
使用该类时,会先加载日志框架,如下:
优先加载顺序:
- Slf4j
- CommonsLogging:Tomcat自带的日志
- Log4J2
- Log4J
- Jdk自带的日志
- NoLogging:没有日志
tryImplementation()
形参是 Runnable,其目的是函数式编程,可以像上图那样,通过 LogFactory::useLog4JLogging 传入方法
在 catch{} 代码块中,没有打印异常信息
private static void tryImplementation(Runnable runnable) {
if (logConstructor == null) {
try {
runnable.run();
} catch (Throwable t) {
// ignore
}
}
}
useLog4JLogging()
以 log4j 为例,useLog4JLogging() 代码如下:
public static synchronized void useLog4JLogging() {
setImplementation(Log4jImpl.class);
}
加载的是 Log4jImpl.class 类
setImplementation() 方法
源码如下:
private static void setImplementation(Class<? extends Log> implClass) {
try {
// 获取 Log4jImpl.class 类的构造方法,该构造方法有一个形参,其类型是 String
Constructor<? extends Log> candidate = implClass.getConstructor(String.class);
// 调用该构造方法创建 日志对象,传入 LogFactory 类全名,其目的是为了下面打印日志
Log log = candidate.newInstance(LogFactory.class.getName());
// 如果是 debug 级,就执行打印
if (log.isDebugEnabled()) {
log.debug("Logging initialized using '" + implClass + "' adapter.");
}
// 将构造对象传成静态变量,供 getLog() 方法使用
logConstructor = candidate;
} catch (Throwable t) {
// 如果抛异常,就抛错,但在 tryImplementation() 方法的 catch{} 代码块没有打印异常,所以这里抛错也没意义
throw new LogException("Error setting Log implementation. Cause: " + t, t);
}
}
Log4jImpl 类
是对 log4j 的简单封装
构造方法
被调用:在 setImplementation() 方法中,获取该类的构造方法,该构造方法有一个形参,其类型是 String
作用:创建log4j的 Logger 对象
public Log4jImpl(String clazz) {
log = Logger.getLogger(clazz);
}
其他方法
不多做解释,就是调用 log4j 的相关方法打印日志
为什么没有日志jar不报错
Log4jImpl 类中 import log4j 的类,如下:
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
为什么没有 log4j 的 jar 包,不会报 找不到类的异常?
原因:只要不调用 LogFactory 类,就不会调用 Log4jImpl 类,也就不会报 找不到类的异常
参考:
https://blog.csdn.net/qq_44041944/article/details/119799019

