# Log
- 首先定义一个基类
org.apache.ibatis.logging.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);
}
# LogImpl
-
使用不同的供应商分别实现这个接口
image.png -
例如slf4j的实现:
image.pngorg.apache.ibatis.logging.slf4j.Slf4jImpl
-
且在每个实现类创建有参的构造方法,用于传递logName
image.png
# LogFactory
-
首先在静态代码块中有序尝试实现支持的日志系统
image.png
-
尝试实现,失败了就捕获异常,继续尝试下一个
private static void tryImplementation(Runnable runnable) {
if (logConstructor == null) {
try {
runnable.run();
} catch (Throwable t) {
// ignore
}
}
}
- 实现逻辑,获取到有参的构造方法,并赋值给类变量
private static 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);
}
}
- 既然已经获取到了
Log
的构造方法,那么在LogFactory.getLog(x)获取Log的时候,通过这个构造方式实例化对象,即可获取到Log
public static Log getLog(Class<?> aClass) {
return getLog(aClass.getName());
}
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);
}
}
# 其他
- 在mybatis源码中,三方的日志依赖都是
<optional>true</optional>
的,不传递日志的依赖,由用户来选择使用的日志供应商。
挺巧妙的~
网友评论