周末又来到了公司吹吹空调,顺便记录下Mybatis的点点滴滴。
首先Mybatis不定义日志系统,完全依赖于第三方系统完成日志记录,利用适配器模式完成实际操作,源码如下:
1:定义一个Log接口,具有如下方法:
public interface Log {
boolean isDebugEnabled();
boolean isTraceEnabled();
void error(String s, Throwable e);
void error(String s);
void debug(String s);
void trace(String s);
void warn(String s);
}
2 :然后引入第三方日志,比如XXXLoggingImpl,实现Log接口,然后用第三方的log去完成真实的动作,如下:
public class Log4jImpl implements Log {
private static final String FQCN = Log4jImpl.class.getName();
private final Logger log;
public Log4jImpl(String clazz) {
log = Logger.getLogger(clazz);
}
@Override
public boolean isDebugEnabled() {
return log.isDebugEnabled();
}
@Override
public boolean isTraceEnabled() {
return log.isTraceEnabled();
}
@Override
public void error(String s, Throwable e) {
log.log(FQCN, Level.ERROR, s, e);
}
@Override
public void error(String s) {
log.log(FQCN, Level.ERROR, s, null);
}
@Override
public void debug(String s) {
log.log(FQCN, Level.DEBUG, s, null);
}
@Override
public void trace(String s) {
log.log(FQCN, Level.TRACE, s, null);
}
@Override
public void warn(String s) {
log.log(FQCN, Level.WARN, s, null);
}
这样的实现类有JakartaCommonsLoggingImpl,Jdk14LoggingImpl,Log4j2AbstractLoggerImpl,NoLoggingImpl,Slf4jImpl,StdOutImpl等,那么问题来了,这些实现类是如何被Mybatis引用的呢?
3 面就是本文的重点LogFactory,LogFactory有个静态的类变量,也就是真正完成日志记录类的构造方法,还有静态代码块,其中完成的动作比较清晰,就是依次完成
实例化各个日志类,如果系统包含对应的日志模块,则反射实例化成功,然后将构造方法时设置为该类的构造方法,如果失败的话,依次尝试下一个,直到最后无日志记录。
Constructor<? extends Log> logConstructor;
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);
}
}
static {
tryImplementation(new Runnable() {
@Override
public void run() {
useSlf4jLogging();
}
});
.......
LogFactory有个静态方法,获得Log的实现类,然后在项目中引用。
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);
}
}