Mybatis框架基础支持层——日志模块(8)
前言:
java开发中常用的日志框架有Log4j,Log4j2,Apache Commons Log,java.util.logging,slf4j等,这些工具对外的接口不尽相同。为了统一这些工具的接口,Mybatis定义了一套统一的日志接口供上层调用,并为上述日志框架提供了相应的适配器。
在Mybatis的日志模块中,使用了适配器模式。Mybatis调用其他日志模块时,使用了其内部接口(org.apache.ibatis.logging.Log接口)。但是第三方日志组件对外提供的接口各不相同,Mybatis为了集成和服用这些第三方日志组件,在其模块中提供了多种Adapter,将这些第三方日志组件对外接口适配成了org.apache.ibatis.logging.Log接口,这样Mybatis内部就可以统一通过org.apache.ibatis.logging.Log接口调用第三方日志组件的功能了。
日志适配器:
Mybatis的日志模块位于org.apache.ibatis.logging包中,改模块中的Log接口定义了日志模块的功能,当然日志适配器也会实现此接口。LogFactory工厂类负责创建对应的日志组件适配器。
LogFactory类解析:
/**
* 在LogFactory类加载时会执行其静态代码块,其逻辑是按序加载并实例化对应的日志适配器,
* 然后使用LogConstructor这个静态字段,记录当前使用的第三方日志组件适配器
*/
public final class LogFactory { /**
* Marker to be used by logging implementations that support markers
*/
public static final String MARKER = "MYBATIS"; /**
* 记录当前使用的第三方日志组件所对应的适配器的构造方法
*/
private static Constructor<? extends Log> logConstructor; /**
* 对每种日志组件调用tryImplementation()进行尝试加载,具体的调用顺序是:
* useSlf4jLogging——>useCommonsLogging——>useLog4J2Logging
* ——>useLog4JLogging——>useJdkLogging——>useNoLogging
*/
static {
tryImplementation(new Runnable() {
@Override
public void run() {
useSlf4jLogging();
}
});
tryImplementation(new Runnable() {
@Override
public void run() {
useCommonsLogging();
}
});
tryImplementation(new Runnable() {
@Override
public void run() {
useLog4J2Logging();
}
});
tryImplementation(new Runnable() {
@Override
public void run() {
useLog4JLogging();
}
});
tryImplementation(new Runnable() {
@Override
public void run() {
useJdkLogging();
}
});
tryImplementation(new Runnable() {
@Override
public void run() {
useNoLogging();
}
});
} private LogFactory() {
// disable construction
} 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);
}
} public static synchronized void useCustomLogging(Class<? extends Log> clazz) {
setImplementation(clazz);
}
/**
* 使用Slf4j日志组件
*/
public static synchronized void useSlf4jLogging() {
setImplementation(org.apache.ibatis.logging.slf4j.Slf4jImpl.class);
} public static synchronized void useCommonsLogging() {
setImplementation(org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl.class);
} public static synchronized void useLog4JLogging() {
setImplementation(org.apache.ibatis.logging.log4j.Log4jImpl.class);
} public static synchronized void useLog4J2Logging() {
setImplementation(org.apache.ibatis.logging.log4j2.Log4j2Impl.class);
} public static synchronized void useJdkLogging() {
setImplementation(org.apache.ibatis.logging.jdk14.Jdk14LoggingImpl.class);
} public static synchronized void useStdOutLogging() {
setImplementation(org.apache.ibatis.logging.stdout.StdOutImpl.class);
} public static synchronized void useNoLogging() {
setImplementation(org.apache.ibatis.logging.nologging.NoLoggingImpl.class);
} /**
* 此方法会先检测logConstructor,若为空则调用runnable.run()方法
*/
private static void tryImplementation(Runnable runnable) {
if (logConstructor == null) {
try {
runnable.run();
} catch (Throwable t) {
// ignore
}
}
} 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字段
logConstructor = candidate;
} catch (Throwable t) {
throw new LogException("Error setting Log implementation. Cause: " + t, t);
}
} }
JDBC调试:
在Mybatis的日志模块中有一个jdbc包,它并不是将日志信息通过jdbc存入数据库,而是通过JDK动态代理的方式,将JDBC操作通过制定的日志框架打印出来。这个功能通常在开发阶段使用,它可以输出sql语句、用户传入的参数、sql影响的行数等信息。对调试程序非常有用。
BaseJdbcLogger是一个抽象类,它是jdbc包下其他Logger类的父类,具体作用请看源码分析,此处不贴源码:

Mybatis框架基础支持层——日志模块(8)的更多相关文章
- Mybatis框架基础支持层——解析器模块(2)
解析器模块,核心类XPathParser /** * 封装了用于xml解析的类XPath.Document和EntityResolver */ public class XPathParser { / ...
- Mybatis框架基础支持层——反射工具箱之Reflector&ReflectorFactory(3)
说明:Reflector是Mybatis反射工具的基础,每个Reflector对应一个类,在Reflector中封装有该类的元信息, 以及基于类信息的一系列反射应用封装API public class ...
- Mybatis框架基础支持层——反射工具箱之MetaClass(7)
简介:MetaClass是Mybatis对类级别的元信息的封装和处理,通过与属性工具类的结合, 实现了对复杂表达式的解析,实现了获取指定描述信息的功能 public class MetaClass { ...
- Mybatis框架基础支持层——反射工具箱之实体属性Property工具集(6)
本篇主要介绍mybatis反射工具中用到的三个属性工具类:PropertyTokenizer.PropertyNamer.PropertyCopier. PropertyTokenizer: 主要用来 ...
- Mybatis框架基础支持层——反射工具箱之对象工厂ObjectFactory&DefaultObjectFactory(5)
ObjectFactory官方简介:MyBatis每次创建结果集对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成. 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认 ...
- Mybatis框架基础支持层——反射工具箱之泛型解析工具TypeParameterResolver(4)
简介:TypeParameterResolver是一个工具类,提供一系列的静态方法,去解析类中的字段.方法返回值.方法参数的类型. 在正式介绍TypeParameterResolver之前,先介绍一个 ...
- MyBatis源码分析-基础支持层反射模块Reflector/ReflectorFactory
本文主要介绍MyBatis的反射模块是如何实现的. MyBatis 反射的核心类Reflector,下面我先说明它的构造函数和成员变量.具体方法下面详解. org.apache.ibatis.refl ...
- 精尽 MyBatis 源码分析 - 基础支持层
该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...
- ERP设计之系统基础管理(BS)-日志模块设计(转载)
原文地址:8.ERP设计之系统基础管理(BS)-日志模块设计作者:ShareERP 日志模块基本要素包括: 用户会话.登录.注销.模块加载/卸载.数据操作(增/删/改/审/弃/关等等).数据恢复.日志 ...
随机推荐
- CSS面试细节整理(一)
最近面试时候发现自己最熟悉的css确实开发中好多细节没注意到,为了防止在栽跟头,打算从头到底捋一遍咯 语法部分: 1.css几种选择器的写法 (1)h1 em {color:red;} (后代选择器) ...
- JDK 1.8判断集合种的元素是否存在相同
List<String> str=new ArrayList<>(); str.add("a"); str.add("a"); str. ...
- js计算指定日期的下一年的日期
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- ndk编译ffmpeg
#!/bin/bash NDK=/opt/android-ndk-r9d SYSROOT=$NDK/platforms/android-9/arch-arm/ TOOLCHAIN=$NDK/toolc ...
- c++ 之bind使用
网络编程中, 经常要使用到回调函数. 当底层的网络框架有数据过来时,往往通过回调函数来通知业务层. 这样可以使网络层只专注于 数据的收发, 而不必关心业务 在c语言中, 回调函数的实现往往通过函数指针 ...
- setData方法修改data中对象或数组的属性值(小程序开发)
今日在开发小程序地图的过程中,遇到一个问题,困扰了我一会 业务如下: 困扰点: 我不知道如何修改data中数组包含的对象是如何修改的:期初的想法还是想共享上面的数据,想的太简单了 正确的解决步骤: 直 ...
- RxJS简介
函数式编程 1.声明式(Declarativ) 和声明式相对应的编程⽅式叫做命令式编程(ImperativeProgramming),命令式编程也是最常见的⼀种编程⽅式. //命令式编程: funct ...
- [MV] - You Give REST a Bad Name
本首歌改自Bon Jovi经典歌曲"You Give Love a Bad Name". 改编的作者是Dylan Beattie, 他是Spotlight的系统架构师. 改编后的歌 ...
- SpringMVC接收json数组对象
最近帮一个妹子解决一个需求,就是前台使用ajax传三个相同的对象,再加一个form表单对象.然后遇到各种问题,终于解决了,@RequestBody接收Json对象字符串 以前,一直以为在Spring ...
- 再见了Server对象,拥抱IHostingEnvironment服务对象(.net core)
一.绝对路径 1.获取应用程序运行当前目录Directory.GetCurrentDirectory(). System.IO命名空间中存在Directory类,提供了获取应用程序运行当前目录的静态方 ...