写给大忙人看的,MyBatis日志如何做到兼容常用的日志框架( 二 )


写给大忙人看的,MyBatis日志如何做到兼容常用的日志框架文章插图
调用了LogFactory类的方法 。
LogFactoryLogFactory工厂是负责创建日志对象对应的适配器 。 LogFactory的静态代码块内按顺序初始化了所有内置的日志
写给大忙人看的,MyBatis日志如何做到兼容常用的日志框架文章插图
再看一下tryImplementation方法 , 如果logConstructor不为空 , 说明当前还没有加载到日志适配器 , 那就继续执行run()方法 , 也就是继续执行useXXXLogging方法 , 而所有的useXXXLogging方法都是调用了setImplementation方法 。
写给大忙人看的,MyBatis日志如何做到兼容常用的日志框架文章插图
下面这里如果加载成功之后就会对logConstructor进行赋值 , 那么后续的方法就不会再执行run()方法 ,而如果抛出异常 , 因为已经被捕获了 , 所以就会继续往后执行静态代码块内的方法 。
写给大忙人看的,MyBatis日志如何做到兼容常用的日志框架文章插图
从上面的LogFactory中我们可以看到 , 初始化的时候就会默认初始化一个日志适配器 , 所以如果我们引用了相关日志所需要的类 , 那么就会按照static代码块内的顺序进行选择一个合适的日志适配器 。
继续回到上面的Configuration里面 , 这里拿到我们配置的日志信息之后 , 会直接调用useCustomLogging方法 , 也就是绕过了上面的logConstructor == null这个判断 , 而直接调用了setImplementation方法 , 所以假如我们配置了日志信息 , 那么会覆盖初始化的日志适配器 。
PS:假如我们配置了一个不存在的日志类 , 那么调用setImplementation方法的时候异常就会被抛出来 , 因为捕获异常的方法是在tryImplementation而不是在setImplementation 。
jdbc logMyBatis的日志包下面还有一个包时jdbc , 这个我们还没有介绍 , 那么jdbc包下面的类又有什么用呢?我们先看一下类图关系:
写给大忙人看的,MyBatis日志如何做到兼容常用的日志框架文章插图
很明显 , MyBatis将日志拆分成了ConnectionLogger , PreparedStatementLogger , ResultSetLogger , StatementLogger四种类型分开处理 , 它们都继承了BaseJdbcLogger类 , 而且实现了InvocationHandler接口 , 也很明显 , 这里用到了JDK动态代理 。
任意点开ConnectionLogger可以发现 , 它是用来代理Connection对象的:
写给大忙人看的,MyBatis日志如何做到兼容常用的日志框架文章插图
其他三个那很明显 , 分别是用来代理PreparedStatement , ResultSet , Statement这三个对象的 。 也就是说MyBatis中日志最终的打印是通过JDK动态代理来实现的 , 而且不同的执行过程分成了四个对象来分别负责对应的日志打印 。
我们继续看一下ConnectionLogger的invoke方法 , 可以看到 , 这里就是打印了一句日志:
写给大忙人看的,MyBatis日志如何做到兼容常用的日志框架文章插图
上面日志打印出来的效果就是我们下面红框中的日志:
写给大忙人看的,MyBatis日志如何做到兼容常用的日志框架文章插图
等等 , 差点被忽悠了 , 这代码里面并没有打印“==>” , 打印出来的这个符号又是怎么来的呢?
那就需要进入debug方法里面继续看一看 , 这个debug方法是在抽象类BaseJdbcLogger里面实现的 , 所以我们还需要看看BaseJdbcLogger类的debug方法 。
写给大忙人看的,MyBatis日志如何做到兼容常用的日志框架文章插图