通过上篇文章《Mybatis 框架日志相关源码分析(一)》了解了 Mybatis 框架通过适配器模式,来整合其它日志框架。而我们都知道要想使用 Log 接口,就需要有具体的实现类对象,那么 Mybatis 是如何创建具体的实现类对象呢?
本文将分析 Mybatis 框架的日志相关源码,了解 Mybatis 如何创建日志实现类对象。Mybatis 在解析到配置中的具体日志 Value 内容时,不仅保存了对应的 Class 属性,还有一行代码:[LogFactory.useCustomLogging(this.logImpl)](https://github.com/mybatis/mybatis-3/blob/d7dcb487afa718b315340f6bd758387804f71298/src/main/java/org/apache/ibatis/session/Configuration.java#L235):
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 方法,此工厂才返回具体的实现类对象。