public final class LogFactory {
//logConstructor存的就是最终选择的日志类型
private static Constructor<? extends Log> logConstructor;
//这里开始给logConstructor变量赋值。
static {
tryImplementation(new Runnable() {
@Override
public void run() {
useSlf4jLogging();
}
});
tryImplementation(new Runnable() {
@Override
public void run() {
useCommonsLogging();
}
});
tryImplementation(new Runnable() {
@Override
public void run() {
useLog4J2Logging();
}
});
tryImplementation(new Runnable() {
@Override
public void run() {
useLog4JLogging();
}
});
tryImplementation(new Runnable() {
@Override
public void run() {
useJdkLogging();
}
});
tryImplementation(new Runnable() {
@Override
public void run() {
useNoLogging();
}
});
}
}
在静态代码快里面都会启动一个异步线程来执行一个方法。来看下tryImplementation方法做了什么操作
private static void tryImplementation(Runnable runnable) {
if (logConstructor == null) {
try {
runnable.run();
} catch (Throwable t) {
// ignore
}
}
}
通过形参传过来的Runnable来里面的任务,但先判断logConstructor是否有值了。
再来看下其中的一个useSlf4jLogging()方法做了
public static synchronized void useSlf4jLogging() {
setImplementation(org.apache.ibatis.logging.slf4j.Slf4jImpl.class);
}
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类型,在通过newInstance来使用代理加载这个类型,如果引入了该jar包,就可以成功加载并创建对象,在赋值给logConstructor。
日志选择顺序如下:
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);
}
1、查看org.apache.ibatis.logging.slf4j.Slf4jImpl.class类,发现里面创建日志对象Logger logger = LoggerFactory.getLogger(clazz);而LoggerFactory是引自org.slf4j.LoggerFactory的包下的,所以这个使用的slf4j打印日志。
2、org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl.class使用的是org.apache.commons.logging.LogFactory来实现打印日志的,也就是JCL
3、org.apache.ibatis.logging.log4j2.Log4j2Impl.class使用的是org.apache.logging.log4j.LogManager来实现日志打印,也就事Log4j2
4、org.apache.ibatis.logging.log4j.Log4jImpl.class使用的是org.apache.log4j.Logger也就是log4j
5、org.apache.ibatis.logging.jdk14.Jdk14LoggingImpl.class使用的是java.util.logging.Logger打印的,也就是JUK
6、org.apache.ibatis.logging.stdout.StdOutImpl.class使用的是System.out.println,System.err.println来打印日志的。
7、org.apache.ibatis.logging.nologging.NoLoggingImpl.class则默认不打印日志。