通过上篇文章《Mybatis 框架日志相关源码分析(一)》了解了 Mybatis 框架通过适配器模式,来整合其它日志框架。而我们都知道要想使用 Log 接口,就需要有具体的实现类对象,那么 Mybatis 是如何创建具体的实现类对象呢?
本文将分析 Mybatis 框架的日志相关源码,了解 Mybatis 如何创建日志实现类对象。
Mybatis 在解析到配置中的具体日志 Value 内容时,不仅保存了对应的 Class<? extends Log> 属性,还有一行代码:LogFactory.useCustomLogging(this.logImpl):
public void setLogImpl(Class<? extends Log> logImpl) {
if (logImpl != null) {
this.logImpl = logImpl;
LogFactory.useCustomLogging(this.logImpl);
}
}
LogFactory 这个类可谓是见名知意,Log 工厂,在设计模式中,这明显就是工厂模式。继续深入看看,这个工厂里面到底是如何创建对象的。首先从入口方法 useCustomLogging 看起,此方法代码很简单,直接调用了 setImplementation():
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 对象,首先获取了 Class 对象构造器,此构造器是带有一个形参为 String.class 。接着就是输出一些日志,最后,将此构造器对象,保存为静态属性:logConstructor 。当有外部代码需要输出日志,通过调用 getLog 方法即可实现日志输出:
public static Log getLog(Class<?> clazz) {
return getLog(clazz.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 通过工厂模式创建日志适配类对象。其中 LogFactory 中保存的是日志适配类的构造器对象,通过调用 getLog 方法,此工厂才返回具体的实现类对象。