Mybatis源码学习-日志模块
所用到的设计模式:
- 适配器模式 (对外提供的日志功能)
- 代理模式 (将日志功能添加到业务中)
代理模式 (静态代理 动态代理)
定义:给目标对象提供一个代理对象,并由代理对象控制目标对象的引用
目的:
1.通过代理对象来访问目标对象,防止直接访问目标对象给系统带来的不必要的复杂性
2.通过代理对象增强原有的业务逻辑(eg:给业务增加日志功能) - 装饰器模式 (真正获取connection对象的时候)
1.Mybatis源码的基本模块
模块如下图:一共16个模块,这16个模块可以分为3层
基础支撑层:专注于底层实现,无业务含义(通用性比较强)
核心处理层:专门处理Mybatis的业务流程实现,依赖于基础支撑层
接口层:对外提供的访问接口,也就是面向SqlSession编程
日志模块
- 如何提供统一的日志级别
前提:Mybatis本身没有日志的实现类,而是接入的第三方日志组件
提供了统一的(log)接口,让客户端面向接口编程,不用关系具体的实现
package org.apache.ibatis.logging;
/**
* @author Clinton Begin
*/
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);
}
- 自动扫描日志,并按顺序加载第三方日志 (顺序slf4j->commomsLogging->log4j2->log4j->jdkLog)
在LogFactory中,有下面的代码块
static {
tryImplementation(LogFactory::useSlf4jLogging);
tryImplementation(LogFactory::useCommonsLogging);
tryImplementation(LogFactory::useLog4J2Logging);
tryImplementation(LogFactory::useLog4JLogging);
tryImplementation(LogFactory::useJdkLogging);
tryImplementation(LogFactory::useNoLogging);
}
该静态代码块的功能是,扫描第三方的日志组件,将他们的构造方法赋给LogFactory,让LogFactory使用该构造方法来实例化日志对象
private static Constructor<? extends Log> logConstructor;
// 真正创建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);
}
}
// 获取第三方日志的构造方法
private static void setImplementation(Class<? extends Log> implClass) {
t