Mybatis日志模块部分源码分析

Mybatis整体架构:


谈谈设计模式的几个原则

单一职责原则:一个类或者一个接口只负责唯一项职责,尽量设计出功能单一的接口;

依赖倒转原则:高层模块不应该依赖低层模块具体实现,解耦高层与低层。既面向接口编程,当实现发生变化时,只需提供新的实现类,不需要修改高层模块代码;

开放-封闭原则:程序对外扩展开放,对修改关闭;换句话说,当需求发生变化时,我们可以通过添加新模块来满足新需求,而不是通过修改原来的实现代码来满足新需求;


先来看日志模块:

1、MyBatis没有提供日志的实现类,需要接入第三方的日志组件,但第三方日志组件都有各自的Log级别,且各不相同,MyBatis统一提供了 trace、debug、warn、error 四个级别;

日志模块采用了适配器设计模式:


MyBatis统一提供了 trace、debug、warn、error 四个级别;

这么熟悉的代码,那一定就是适配器设计模式啦。

2、再看自动扫描日志实现,并且第三方日志插件加载优先级如下:slf4J → commonsLoging → Log4J2 → Log4J  → JdkLog是如何实现的。

那就需要看这个类:LogFactory

这个类加载的时候,就会执行静态代码块。看一下这个静态代码块:


那么就点进 tryImplementation这个方法,这个tryImplementation方法和我开篇讲的java8那个例子一样。

那么我们可以开始写测试类,来Debug一下Mybatis源码,看一下是如何进行调用的。

第一个断点打在这里。

第二个断点打在这里

无论如何首先应该是加载静态代码块,就别看getLog方法了。

那么就看静态代码块,到这一步怎么走?是先看外面的方法还是里面的方法?

根据文章开头的代码结果来看,肯定是先走tryImplementation,LogFactory::useSlf4JLogging是runnable.run()的时候才去执行的。

所以看一下tryImplementation这个方法:显然logConstructor是null,然后进入了if

然后继续往下运行runnable.run()的时候,跳到了这里,这个useSlf4jLogging正是tryImplementation(LogFactory::useSlf4jLogging);里面的这个

那就继续进入setImplementation方法:try内运行完毕之后,可以看到logConstructor= candidate = slf4jImpl的全限定名。

然后代码继续运行,最终就跳回到了这里

结论就是 runnable.run()之前 logConstructor是null的,但是run了之后 logConstructor就不在是null了。道理和开篇的那个小案例是一样的。


继续走第二个,一样也是进tryImplementation方法,但是此时logConstructor是有值的,等于

但是此时logConstructor是有值的,等于看下图Variables,等于上一个tryImplementation执行后的logConstructor = Slf4jImpl的类的构造器对象

所以进第二个tryImplementation方法的时候 就不走 if 了。直接跳出

看下图,直接就跳过if判断了

所以,static代码块之后的第三方日志包都不加载。而且静态代码块的性质是只加载一次,也就是说,如果项目里有这6个第三包日志包的时候加载顺序是slf4J -> commonsLoging -> log4J2 -> log4J ->JdkLog ->NoLogging,并且是加载了slf4j的话,就不加在其他的第三方日志包了,如果项目里没有slf4j的时候,那就优先加载commonsLoging,加载了commonsLoging的话,就不会加载剩下的了,如果没有commonsLoging的话,那就加载log4J2,依次类推。


有同学就会问,你的Demo类里还有代码呢,

这些断点往下走,不会进入LogFactory类的static吗,不会的,static只加载一次,技术把断点继续下去放到红框这里的话

然后把断点想放过去放到static,根本就放不过去。

所以整个日志加载顺序大致是这个样子。

3、日志的使用要优雅的嵌入到主体功能中;使用动态代理嵌入。

日志模块有一个jdbc包

看一下BaseJdbcLogger这个抽象类,父类。

这些注释的属性,在静态代码块里初始化,我的mybatis版本比较新是采用了stream来初始化的属于java8的语法,

展开阅读全文

本文系作者在时代Java发表,未经许可,不得转载。

如有侵权,请联系nowjava@qq.com删除。

编辑于

关注时代Java

关注时代Java