日志模块
Mybatis内部提供了日志模块,用于记录框架内部异常与调试信息;
日志实现使用了经典的适配器模式,mybatis自己本身不提供日志功能,而是依赖其他的日志框架来实现;内部支持的优先级是:SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING
统一封装
由于各个厂商提供的日志api,日志级别等都不尽相同,所以mybatis对所有支持的日志框架做了封装,自定义了日志打印级别
error (错误) > warn (警告) > debug(调试信息)>trace
mybatis 里定了了统一的日志接口,Log接口并定义了一系列的接口
org.apache.ibatis.logging.Log
提供的实现类
日志集成核心类 org.apache.ibatis.logging.LogFactory
在LogFactory的静态方法里按照特定的顺序,寻找并加载对于的第三方日志组件,
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);
}
}
这个方法主要功能是去加载提供的实现类,这些实现类里引用了第三方的类,如果项目中没有提供对于的jar包则该方法会抛错,然后异常会传递到 tryImplementation方法;
tryImplementation 方法里会先判断是否已经加载了日志组件,如果已经加载了则不会继续处理;并且这个方法做了异常的吞没,如果没有对于的日志组件也不会影响下一个组件的加载流程;
如果实例化特制类成功,则会将对于的类构造器赋值给 logConstructor,以便后续实例化
private static void tryImplementation(Runnable runnable) {
if (logConstructor == null) {
try {
runnable.run();
} catch (Throwable t) {
// ignore
}
}
}
下面以 org.apache.ibatis.logging.log4j.Log4jImpl 为例做分析
这个类适配的 org.apache.log4j日志组件,在类里有一个成员变量
private final Logger log;
Log4jImpl这个类相当于是将log4j的功能翻译成了Mybatis的功能,做了api的适配
SQL打印
如果想在控制台或者日志文件里打印sql只需要在mybatis的总配置文件的setting里加上配置即可
以打印到控制台为例:
<settings>
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>