Mybatis适配器
周杰伦本人 人气:0Mybatis的日志模块的适配器模式
我们在开发中日志是必不可少的一部分,而市场中有很多日志框架供我们使用,mybatis作为一个开源框架需要兼容这些框架,mybatis用了适配器模式来兼容这些框架,适配器模式就是通过组合的方式,将需要适配的类转为使用者能够使用的接口
下面咱们分析一下mybatis的日志模块
mybatis定义了自己的Log接口
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); }
这里定义了一些常用的方法
LogFactory的静态代码块加载对应是日志适配器:
日志工厂类LogFactory
static { tryImplementation(LogFactory::useSlf4jLogging); tryImplementation(LogFactory::useCommonsLogging); tryImplementation(LogFactory::useLog4J2Logging); tryImplementation(LogFactory::useLog4JLogging); tryImplementation(LogFactory::useJdkLogging); tryImplementation(LogFactory::useNoLogging); } private static void tryImplementation(Runnable runnable) { if (logConstructor == null) { try { runnable.run(); } catch (Throwable t) { // ignore } } } public static synchronized void useLog4JLogging() { setImplementation(org.apache.ibatis.logging.log4j.Log4jImpl.class); }
当logConstructor用来记录日志适配器的构造方法,当logConstructor不为空的时候就不再加载其他的日志适配器了。
分析一下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); } }
- 获取适配器的构造方法
- 然后获取这个适配器的实例,如果获取成功,把它的构造方法记录在logConstructor中,否则就会抛出异常
下面就分析一下Log4jImpl类:
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); } }
Log4jImpl是一个适配器类,它实现了Mybatis自定义的Log接口,它的成员变量Logger是log4j里的类,我们要做的是调用Log接口的方法就可以使用log4j,Logger是需要我们适配的类,因此我们在实现Log接口的方法的时候调用Logger中的方法来完成适配,这就是适配器模式的实现
总结
Mybatis日志模块用到了适配器模式,Log接口是目标接口,Logger等各种日志框架的类是需要我们适配的类,而是适配器是Log4jImpl、Slf4jImpl等适配类
加载全部内容