点击上方蓝色“方志朋”,选择“设为星标”

回复“666”获取独家整理的学习资料!

来源:blog.csdn.net/zwx900102/article/details/109025846

目录

  • 前言

  • MyBatis日志分类

    • 简单谈谈SLF4J

  • MyBatis日志实现原理

    • 日志的解析

    • LogFactory

    • jdbc log

  • 总结

前言

日志,在我们开发中是一个非常重要的话题,良好的日志打印可以帮助我们快速的定位问题,可能现在我们开发用到最多的日志框架就是slf4j了,但是日志还有其他很多优秀的框架,比如:Apache Common Log,Log4j,java.util.logging等。

MyBatis作为一款优秀的ORM框架,定义了一套统一的日志接口供应用层调用,而底层却利用适配器模式兼容了我们上面所列出来的常用日志框架。

MyBatis日志分类

在介绍MyBatis的全局配置文件的时候,我们提到setting内有一个属性logImpl,可以配置的选项有:SLF4J,LOG4J,LOG4J2,JDK_LOGGING,COMMONS_LOGGING,STDOUT_LOGGING,NO_LOGGING。

这就说明MyBatis支持六种日志类型(NO_LOGGING是不打印日志)。我们看一下MyBatis的日志模块也可以很明显的看出六种日志类型:

它们的对应关系为:

PS:需要注意的是,SLF4J并不是一个具体的日志框架,也就是我们不能单独只配置SLF4J而不引入其他任何具体的日志框架。

简单谈谈SLF4J

SLF4J:简单日记门面。(英文全称为simple logging Facade for Java),这个是用来为各种日志框架提供一个简单的统一的接口,这样使得我们在切换日志框架的时候可以直接替换jar包就可以了,而无需修改源代码。

logback我想大家都用过,logback是一个实现了具体日志打印的框架,但是MyBatis上面列出来的分类并没有支持logback,它又为什么能够打印呢?这就是SLF4J的作用了,因为logback也实现了SLF4J提供的接口,所以我们需要将logback和SLF4J结合配置使用才行。而后面的介绍中也可以看到,MyBatis中如果我们不指定日志种类的时候,优先选择的就是SLF4J,这正是因为SLF4J可以和其他许多日志框架一起结合来使用。

那么假如我们指定了日志类型为SLF4J,但是不引入其他任何实现呢?

答案就是MyBatis不会打印任何日志出来,下图就是只配置了SLF4J而没有引入其他任何实现的警告信息:

可以看到这里提示我们SLF4J没有任何实现,而后面的sql语句和参数这些信息也没有打印出来。

MyBatis日志实现原理

日志的解析

老规矩,我们还是先找到加载mybatis-config配置文件中的解析日志的源码:

这里首先会根据我们配置的属性作为别名去TypeAliasRegistry类中查找对应的类,如果不存在这个别名,那就会把我们配置的属性直接通过Class.forName去查找日志类,所以看到这里就明白我们可以自定义日志类,只要实现Log接口就行,然后配置我们自己的类名就行了。

虽然别名都存在TypeAliasRegistry类里面,但是我们前面介绍MyBatis配置文件的时候,列出了TypeAliasRegistry类中默认初始化的别名,并没有看到日志相关类的别名,那么日志的别名又是在哪里配置的呢?我们打开Configuration类:

可以看到Configuration的构造方法里面也初始化了一些别名注册到TypeAliasRegistry类了。

接下来我们看看读取到日志类之后调用了setLogImpl做了什么事情:

调用了LogFactory类的方法。

LogFactory

LogFactory工厂是负责创建日志对象对应的适配器。

LogFactory的静态代码块内按顺序初始化了所有内置的日志

再看一下tryImplementation方法,如果logConstructor不为空,说明当前还没有加载到日志适配器,那就继续执行run()方法,也就是继续执行useXXXLogging方法,而所有的useXXXLogging方法都是调用了setImplementation方法。

下面这里如果加载成功之后就会对logConstructor进行赋值,那么后续的方法就不会再执行run()方法, 而如果抛出异常,因为已经被捕获了,所以就会继续往后执行静态代码块内的方法。

从上面的LogFactory中我们可以看到,初始化的时候就会默认初始化一个日志适配器,所以如果我们引用了相关日志所需要的类,那么就会按照static代码块内的顺序进行选择一个合适的日志适配器。

继续回到上面的Configuration里面,这里拿到我们配置的日志信息之后,会直接调用useCustomLogging方法,也就是绕过了上面的logConstructor == null这个判断,而直接调用了setImplementation方法,所以假如我们配置了日志信息,那么会覆盖初始化的日志适配器。

PS:假如我们配置了一个不存在的日志类,那么调用setImplementation方法的时候异常就会被抛出来,因为捕获异常的方法是在tryImplementation而不是在setImplementation。

jdbc log

MyBatis的日志包下面还有一个包时jdbc,这个我们还没有介绍,那么jdbc包下面的类又有什么用呢?我们先看一下类图关系:

很明显,MyBatis将日志拆分成了ConnectionLogger,PreparedStatementLogger,ResultSetLogger,StatementLogger四种类型分开处理,它们都继承了BaseJdbcLogger类,而且实现了InvocationHandler接口,也很明显,这里用到了JDK动态代理。

任意点开ConnectionLogger可以发现,它是用来代理Connection对象的:

其他三个那很明显,分别是用来代理PreparedStatement,ResultSet,Statement这三个对象的。也就是说MyBatis中日志最终的打印是通过JDK动态代理来实现的,而且不同的执行过程分成了四个对象来分别负责对应的日志打印。

我们继续看一下ConnectionLogger的invoke方法,可以看到,这里就是打印了一句日志:

上面日志打印出来的效果就是我们下面红框中的日志:

等等,差点被忽悠了,这代码里面并没有打印“==>”,打印出来的这个符号又是怎么来的呢?

那就需要进入debug方法里面继续看一看,这个debug方法是在抽象类BaseJdbcLogger里面实现的,所以我们还需要看看BaseJdbcLogger类的debug方法。

可以看到这里打印的时候拼接了一个前缀:

PS:queryStack是查询层数,如果没有嵌套查询则queryStack=1

总结

本文主要分析了MyBatis日志的加载原理,并对LogFactory作为适配器对象工厂是如何选择日志适配器对象进行了分析。最后分析了MyBatis是如何通过动态代理将不同日志类型分为不同对象来实现日志打印功能的。

热门内容:
  • 这玩意比ThreadLocal叼多了,吓得我赶紧分享出来。

  • Spring Boot 无侵入式 实现 API 接口统一 JSON 格式返回

  • MySQL大表优化方案

  • 从零搭建 Spring Cloud 服务(超级详细)

最近面试BAT,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。
明天见(。・ω・。)ノ♡

MyBatis 如何兼容所有日志框架?相关推荐

  1. MyBatis日志到底是如何做到兼容所有常用日志框架的?

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 作者 | 双子孤狼 来源 | https://blog. ...

  2. 的日志在哪里_写给大忙人看的,MyBatis日志如何做到兼容所有常用的日志框架?...

    前言 日志,在我们开发中是一个非常重要的话题,良好的日志打印可以帮助我们快速的定位问题,可能现在我们开发用到最多的日志框架就是slf4j了,但是日志还有其他很多优秀的框架,比如:Apache Comm ...

  3. 萌新发问:MyBatis日志到底是如何做到兼容所有常用日志框架的?

    点击上方 好好学java ,选择 星标 公众号重磅资讯,干货,第一时间送达 今日推荐:推荐 19 个 github 超牛逼项目!个人原创100W +访问量博客:点击前往,查看更多 作者:双子孤狼 bl ...

  4. Java项目如何统一日志框架?

    在程序运行的过程中,我们需要在重要的代码逻辑分支点,将关键的程序运行状态信息打印出来,便于我们对程序调试和观察.java项目中有成熟高性能的日志框架,很方便地集成到项目中实现我们对关键信息的打印输出. ...

  5. 多种java 日志框架【超详细图文】

    一.目标 日志的作用和目的 日志的框架 JUL的使用 LOG4J的使用 JCL的使用 二.日志的概念 2.1 日志文件 日志文件是用于记录系统操作事件的文件集合,可分为事件日志和消息日志.具有处理历史 ...

  6. Java 日志框架适配/冲突解决方案(值得收藏)

    欢迎关注方志朋的博客,回复"666"获面试宝典 来源:juejin.cn/post/6945220055399399455 前言 你是否遇到过配置了日志,但打印不出来的情况? 你是 ...

  7. 可能是全网最全,JAVA日志框架适配/冲突解决方案,可以早点下班了

    点击关注公众号,Java干货及时送达 你是否遇到过配置了日志,但打印不出来的情况? 你是否遇到过配置了logback,启动时却提示log4j错误的情况?像下面这样: log4j:WARN No app ...

  8. spring日志报错提醒_Spring Boot 2.x : 整合日志框架 Log4j2

    日志框架概述 在一个 web 项目建设中,如果说第一件事是 Spring 框架的搭建,那么第二件事就是日志框架的搭建,线上 web 项目的日志可能是我们了解项目运行的唯一方式. 常用日志框架 java ...

  9. Spring Boot与日志 ——日志框架、日志配置||SLF4j使用||SpringBoot日志关系||切换日志框架

    1.日志框架 SLF4j使用 1.如何在系统中使用SLF4j 以后开发的时候,日志记录方法的调用,不应该来直接调用日志的实现类,而是调用日志抽象层里面的方法: 给系统里面导入slf4j的jar和 lo ...

最新文章

  1. 以ajax请求方式进行文件下载操作失败的原因及解决方案
  2. 141 springmvc中 转发 与 重定向
  3. jni java_JNI 常见用法
  4. python重复字符串n次_python装饰器听了N次也没印象,读完这篇你就懂了
  5. Nginx使用brotli代替gzip
  6. ASP.NET Core Razor 视图组件
  7. myeclipse下Tomcat java.lang.OutOfMemory Error: Java heap space
  8. 一层循环时间复杂度_渐进时间复杂度分析
  9. poj 1469(二分图最大匹配)
  10. 【Java】JSON转EXCEL,支持多个数组生成多个sheet、附表头替换
  11. 舆情监控系统python开源_舆情监测系统开源
  12. 华为网络技术大赛笔记——服务器概述
  13. The Framework For Love
  14. 隐私保护与生成模型: 差分隐私GAN的梯度脱敏方法
  15. 2023年技术分析|血氧仪芯片方案
  16. SDHK_Tool.Static.SS_EulerAngleConversion 欧拉角,角度转换计算
  17. WebMvcConfigurer配置HandlerInterceptor拦截器失效
  18. c语言程序 中断函数示例,单片机_C语言函数_中断函数(中断服务程序)
  19. C++ Eigen类
  20. ubuntu14下安裝及搜狗拼音输入法打不出汉字的解决方法

热门文章

  1. RXJAVA之变换操作
  2. Android 曲线动画animation,类似加入购物车动画
  3. 页面的前进/后退/刷新方法
  4. 如何查看服务器有多少网站--免费工具
  5. 从网页模版切图到网页生成全攻略(转)
  6. 【NCEPU】吴丹飞:新闻文章点击预测
  7. 【青少年编程】【四级】绘制花瓣
  8. 【青少年编程】【一级】小镇一日游
  9. 【直播】鱼佬:心跳信号分类赛高分突破
  10. 数据结构与算法:04 C#面向对象设计 II