中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

MyBatis日志為什么可以兼容其他的日志框架

發布時間:2020-11-11 14:38:05 來源:億速云 閱讀:186 作者:Leah 欄目:開發技術

本篇文章為大家展示了MyBatis日志為什么可以兼容其他的日志框架,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

前言

日志,在我們開發中是一個非常重要的話題,良好的日志打印可以幫助我們快速的定位問題,可能現在我們開發用到最多的日志框架就是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的日志模塊也可以很明顯的看出六種日志類型:

MyBatis日志為什么可以兼容其他的日志框架

它們的對應關系為:

日志屬性對應日志模塊包名實現方式
SLF4Jslf4j使用SLF4J日志框架實現
LOG4Jlog4j使用Log4J日志框架實現(1.x版本)
LOG4J2log4j2使用Log4J日志框架實現(2.x版本)
JDK_LOGGINGjdk14使用java.util.logging實現
COMMONS_LOGGINGcommons使用Apache Commons Logging實現
STDOUT_LOGGINGstdout使用System類實現
NO_LOGGINGnologging不打印日志

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而沒有引入其他任何實現的警告信息:

MyBatis日志為什么可以兼容其他的日志框架

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

MyBatis日志實現原理

日志的解析

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

MyBatis日志為什么可以兼容其他的日志框架

MyBatis日志為什么可以兼容其他的日志框架

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

MyBatis日志為什么可以兼容其他的日志框架

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

MyBatis日志為什么可以兼容其他的日志框架

調用了LogFactory類的方法。

LogFactory

LogFactory工廠是負責創建日志對象對應的適配器。
LogFactory的靜態代碼塊內按順序初始化了所有內置的日志

MyBatis日志為什么可以兼容其他的日志框架

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

MyBatis日志為什么可以兼容其他的日志框架

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

MyBatis日志為什么可以兼容其他的日志框架

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

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

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

jdbc log

MyBatis的日志包下面還有一個包時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日志為什么可以兼容其他的日志框架

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

MyBatis日志為什么可以兼容其他的日志框架

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

上述內容就是MyBatis日志為什么可以兼容其他的日志框架,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

高邑县| 客服| 乐山市| 琼结县| 古蔺县| 威海市| 牟定县| 永德县| 绵阳市| 沁源县| 云阳县| 乳山市| 福泉市| 霍州市| 云南省| 靖边县| 台中县| 青田县| 会泽县| 城固县| 兴城市| 远安县| 华池县| 聂拉木县| 襄汾县| 法库县| 盖州市| 丰镇市| 图木舒克市| 岳普湖县| 巴楚县| 施秉县| 富顺县| 禹城市| 兴国县| 唐海县| 金溪县| 伊宁市| 永兴县| 米林县| 抚远县|