最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解MyBatis日志如何做到兼容所有常用的日志框架

 更新時間:2020年11月10日 15:00:26   作者:雙子孤狼  
這篇文章主要介紹了詳解MyBatis日志如何做到兼容所有常用的日志框架,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

日志,在我們開發(fā)中是一個非常重要的話題,良好的日志打印可以幫助我們快速的定位問題,可能現(xiàn)在我們開發(fā)用到最多的日志框架就是slf4j了,但是日志還有其他很多優(yōu)秀的框架,比如:Apache Common Log,Log4j,java.util.logging等。MyBatis作為一款優(yōu)秀的ORM框架,定義了一套統(tǒng)一的日志接口供應(yīng)用層調(diào)用,而底層卻利用適配器模式兼容了我們上面所列出來的常用日志框架。

MyBatis日志分類

在介紹MyBatis的全局配置文件的時候,我們提到setting內(nèi)有一個屬性logImpl,可以配置的選項有:SLF4J,LOG4J,LOG4J2,JDK_LOGGING,COMMONS_LOGGING,STDOUT_LOGGING,NO_LOGGING。
這就說明MyBatis支持六種日志類型(NO_LOGGING是不打印日志)。我們看一下MyBatis的日志模塊也可以很明顯的看出六種日志類型:

在這里插入圖片描述

它們的對應(yīng)關(guān)系為:

日志屬性 對應(yīng)日志模塊包名 實現(xiàn)方式
SLF4J slf4j 使用SLF4J日志框架實現(xiàn)
LOG4J log4j 使用Log4J日志框架實現(xiàn)(1.x版本)
LOG4J2 log4j2 使用Log4J日志框架實現(xiàn)(2.x版本)
JDK_LOGGING jdk14 使用java.util.logging實現(xiàn)
COMMONS_LOGGING commons 使用Apache Commons Logging實現(xiàn)
STDOUT_LOGGING stdout 使用System類實現(xiàn)
NO_LOGGING nologging 不打印日志

PS:需要注意的是,SLF4J并不是一個具體的日志框架,也就是我們不能單獨只配置SLF4J而不引入其他任何具體的日志框架。

簡單談?wù)凷LF4J

SLF4J:簡單日記門面。(英文全稱為simple logging Facade for Java),這個是用來為各種日志框架提供一個簡單的統(tǒng)一的接口,這樣使得我們在切換日志框架的時候可以直接替換jar包就可以了,而無需修改源代碼。

logback我想大家都用過,logback是一個實現(xiàn)了具體日志打印的框架,但是MyBatis上面列出來的分類并沒有支持logback,它又為什么能夠打印呢?這就是SLF4J的作用了,因為logback也實現(xiàn)了SLF4J提供的接口,所以我們需要將logback和SLF4J結(jié)合配置使用才行。而后面的介紹中也可以看到,MyBatis中如果我們不指定日志種類的時候,優(yōu)先選擇的就是SLF4J,這正是因為SLF4J可以和其他許多日志框架一起結(jié)合來使用。

那么假如我們指定了日志類型為SLF4J,但是不引入其他任何實現(xiàn)呢?
答案就是MyBatis不會打印任何日志出來,下圖就是只配置了SLF4J而沒有引入其他任何實現(xiàn)的警告信息:

在這里插入圖片描述

可以看到這里提示我們SLF4J沒有任何實現(xiàn),而后面的sql語句和參數(shù)這些信息也沒有打印出來。

MyBatis日志實現(xiàn)原理

日志的解析

老規(guī)矩,我們還是先找到加載mybatis-config配置文件中的解析日志的源碼:

在這里插入圖片描述

在這里插入圖片描述

這里首先會根據(jù)我們配置的屬性作為別名去TypeAliasRegistry類中查找對應(yīng)的類,如果不存在這個別名,那就會把我們配置的屬性直接通過Class.forName去查找日志類,所以看到這里就明白我們可以自定義日志類,只要實現(xiàn)Log接口就行,然后配置我們自己的類名就行了。雖然別名都存在TypeAliasRegistry類里面,但是我們前面介紹MyBatis配置文件的時候,列出了TypeAliasRegistry類中默認(rèn)初始化的別名,并沒有看到日志相關(guān)類的別名,那么日志的別名又是在哪里配置的呢?我們打開Configuration類:

在這里插入圖片描述

可以看到Configuration的構(gòu)造方法里面也初始化了一些別名注冊到TypeAliasRegistry類了。
接下來我們看看讀取到日志類之后調(diào)用了setLogImpl做了什么事情:

在這里插入圖片描述

調(diào)用了LogFactory類的方法。

LogFactory

LogFactory工廠是負(fù)責(zé)創(chuàng)建日志對象對應(yīng)的適配器。
LogFactory的靜態(tài)代碼塊內(nèi)按順序初始化了所有內(nèi)置的日志

在這里插入圖片描述

再看一下tryImplementation方法,如果logConstructor不為空,說明當(dāng)前還沒有加載到日志適配器,那就繼續(xù)執(zhí)行run()方法,也就是繼續(xù)執(zhí)行useXXXLogging方法,而所有的useXXXLogging方法都是調(diào)用了setImplementation方法。

在這里插入圖片描述

下面這里如果加載成功之后就會對logConstructor進(jìn)行賦值,那么后續(xù)的方法就不會再執(zhí)行run()方法, 而如果拋出異常,因為已經(jīng)被捕獲了,所以就會繼續(xù)往后執(zhí)行靜態(tài)代碼塊內(nèi)的方法。

在這里插入圖片描述

從上面的LogFactory中我們可以看到,初始化的時候就會默認(rèn)初始化一個日志適配器,所以如果我們引用了相關(guān)日志所需要的類,那么就會按照static代碼塊內(nèi)的順序進(jìn)行選擇一個合適的日志適配器。

繼續(xù)回到上面的Configuration里面,這里拿到我們配置的日志信息之后,會直接調(diào)用useCustomLogging方法,也就是繞過了上面的logConstructor == null這個判斷,而直接調(diào)用了setImplementation方法,所以假如我們配置了日志信息,那么會覆蓋初始化的日志適配器。

PS:假如我們配置了一個不存在的日志類,那么因為它是直接調(diào)用setImplementation方法,所以異常就會被拋出來,不拋異常的方法是tryImplementation而不是setImplementation。

jdbc log

MyBatis的日志包下面還有一個包時jdbc,這個我們還沒有介紹,那么jdbc包下面的類又有什么用呢?我們先看一下類圖關(guān)系:

在這里插入圖片描述

很明顯,MyBatis將日志拆分成了ConnectionLogger,PreparedStatementLogger,ResultSetLogger,StatementLogger四種類型分開處理,它們都繼承了BaseJdbcLogger類,而且實現(xiàn)了InvocationHandler接口,也很明顯,這里用到了JDK動態(tài)代理。

任意點開ConnectionLogger可以發(fā)現(xiàn),它是用來代理Connection對象的:

在這里插入圖片描述

其他三個那很明顯,分別是用來代理PreparedStatement,ResultSet,Statement這三個對象的。也就是說MyBatis中日志最終的打印是通過JDK動態(tài)代理來實現(xiàn)的,而且不同的執(zhí)行過程分成了四個對象來分別負(fù)責(zé)對應(yīng)的日志打印。

我們繼續(xù)看一下ConnectionLogger的invoke方法,可以看到,這里就是打印了一句日志:

在這里插入圖片描述

上面日志打印出來的效果就是我們下面紅框中的日志:

在這里插入圖片描述

等等,差點被忽悠了,這代碼里面并沒有打印“==>”,打印出來的這個符號又是怎么來的呢?

那就需要進(jìn)入debug方法里面繼續(xù)看一看,這個debug方法是在抽象類BaseJdbcLogger里面實現(xiàn)的,所以我們還需要看看BaseJdbcLogger類的debug方法。

在這里插入圖片描述

可以看到這里打印的時候拼接了一個前綴:

在這里插入圖片描述

PS:queryStack是查詢層數(shù),如果沒有嵌套查詢則queryStack=1

總結(jié)

本文主要分析了MyBatis日志的加載原理,并對LogFactory作為適配器對象工廠是如何選擇日志適配器對象進(jìn)行了分析。最后分析了MyBatis是如何通過動態(tài)代理將不同日志類型分為不同對象來實現(xiàn)日志打印功能的。

到此這篇關(guān)于詳解MyBatis日志如何做到兼容所有常用的日志框架的文章就介紹到這了,更多相關(guān)MyBatis兼容所有日志框架內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解Java線程池如何統(tǒng)計線程空閑時間

    詳解Java線程池如何統(tǒng)計線程空閑時間

    這篇文章主要和大家分享一個面試題:Java線程池是怎么統(tǒng)計線程空閑時間?文中的示例代碼講解詳細(xì),對我們掌握J(rèn)ava有一定幫助,需要的可以參考一下
    2022-11-11
  • 一文詳解SpringBoot?Redis多數(shù)據(jù)源配置

    一文詳解SpringBoot?Redis多數(shù)據(jù)源配置

    Spring?Boot默認(rèn)只允許一種?Redis?連接池配置,且配置受限于?Lettuce?包,不夠靈活,所以本文將為大家介紹如何自定義Redis配置方案實現(xiàn)多數(shù)據(jù)源支持,需要的可以參考下
    2024-11-11
  • Java如何通過屬性名獲取Object對象屬性值

    Java如何通過屬性名獲取Object對象屬性值

    這篇文章主要介紹了Java如何通過屬性名獲取Object對象屬性值問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • 最簡單的Spring Cloud教程第一篇:服務(wù)的注冊與發(fā)現(xiàn)(Eureka)

    最簡單的Spring Cloud教程第一篇:服務(wù)的注冊與發(fā)現(xiàn)(Eureka)

    這篇文章主要給大家介紹了關(guān)于Spring Cloud服務(wù)的注冊與發(fā)現(xiàn)(Eureka)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用spring cloud具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧。
    2017-08-08
  • springcloud組件技術(shù)分享(推薦)

    springcloud組件技術(shù)分享(推薦)

    Spring Cloud 是一系列框架的有序集合,它利用 Spring Boot 的開發(fā)便利性簡化了分布式系統(tǒng)的開發(fā),比如服務(wù)發(fā)現(xiàn)、服務(wù)網(wǎng)關(guān)、服務(wù)路由、鏈路追蹤等。這篇文章主要介紹了springcloud組件技術(shù)分享,需要的朋友可以參考下
    2020-10-10
  • Java 線程池詳解及實例代碼

    Java 線程池詳解及實例代碼

    這篇文章主要介紹了Java 線程池的相關(guān)資料,并符實例代碼,幫助大家學(xué)習(xí)參考,需要的朋友可以參考下
    2016-09-09
  • Java多線程中ThreadLocal解讀

    Java多線程中ThreadLocal解讀

    這篇文章主要介紹了Java多線程中ThreadLocal解讀,??多線程訪問同一個共享變量的時候容易出現(xiàn)并發(fā)問題,因此為了保證線程安全性,我們都會采用加鎖的方式,而ThreadLocal是除加鎖方式之外的另一種保證線程安全性的方法,需要的朋友可以參考下
    2023-09-09
  • SpringBoot實現(xiàn)啟動項目后立即執(zhí)行的方法總結(jié)

    SpringBoot實現(xiàn)啟動項目后立即執(zhí)行的方法總結(jié)

    在項目開發(fā)中某些場景必須要用到啟動項目后立即執(zhí)行方式的功能,所以這篇文章就來和大家聊聊實現(xiàn)立即執(zhí)行的幾種方法,希望對大家有所幫助
    2023-05-05
  • Java中的volatile關(guān)鍵字原理深入解析

    Java中的volatile關(guān)鍵字原理深入解析

    這篇文章主要介紹了Java中的volatile關(guān)鍵字原理深入解析,volatile是Java 編程語言允許線程訪問共享變量,為了確保共享變量能被準(zhǔn)確和一致地更新,線程應(yīng)該確保通過排他鎖單獨獲得這個變量,需要的朋友可以參考下
    2023-12-12
  • java獲取系統(tǒng)路徑字體、得到某個目錄下的所有文件名、獲取當(dāng)前路徑

    java獲取系統(tǒng)路徑字體、得到某個目錄下的所有文件名、獲取當(dāng)前路徑

    這篇文章主要介紹了java獲取系統(tǒng)路徑字體、得到某個目錄下的所有文件名、獲取當(dāng)前路徑,需要的朋友可以參考下
    2014-04-04

最新評論

田阳县| 特克斯县| 双辽市| 新邵县| 麻城市| 谢通门县| 桃源县| 阳西县| 余江县| 甘泉县| 寻乌县| 陇川县| 大荔县| 平罗县| 聊城市| 亳州市| 北流市| 六安市| 安乡县| 宜春市| 成武县| 抚宁县| 通江县| 衢州市| 朝阳县| 达日县| 井研县| 河北省| 蓝山县| 淳化县| 临泉县| 开阳县| 竹北市| 建宁县| 油尖旺区| 布拖县| 伊宁市| 平泉县| 红原县| 南丹县| 策勒县|