日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當前位置:首頁 > > 架構師社區(qū)
[導讀]我們在使用mybatis時,如果出現(xiàn)sql問題,一般會把mybatis配置文件中的logging.level參數(shù)改成debug,這樣就能在日志中看到某個mapper最終執(zhí)行sql、入?yún)⒑陀绊憯?shù)據(jù)行數(shù)。我們拿到sql和入?yún)?,手動拼接成完整的sql,然后將該sql在數(shù)據(jù)庫中執(zhí)行一下,就基本能定位到問題原因。mybatis的日志功能使用起來還是非常方便的,大家有沒有想過它是如何設計的呢?

引言

我們在使用mybatis時,如果出現(xiàn)sql問題,一般會把mybatis配置文件中的logging.level參數(shù)改成debug,這樣就能在日志中看到某個mapper最終執(zhí)行sql、入?yún)⒑陀绊憯?shù)據(jù)行數(shù)。我們拿到sql和入?yún)?,手動拼接成完整的sql,然后將該sql在數(shù)據(jù)庫中執(zhí)行一下,就基本能定位到問題原因。mybatis的日志功能使用起來還是非常方便的,大家有沒有想過它是如何設計的呢?

從logging目錄開始

我們先看一下mybatislogging目錄,該目錄的功能決定了mybatis使用什么日志工具打印日志。

logging目錄結構如下:

mybatis日志功能是如何設計的?

它里面除了jdbc目錄,還包含了7個子目錄,每一個子目錄代表一種日志打印工具,目前支持6種日志打印工具和1種非日志打印工具。我們用一張圖來總結一下

mybatis日志功能是如何設計的?

除了上面的8種日志工具之外,它還抽象出一個Log接口,所有的日志打印工具必須實現(xiàn)該接口,后面可以面向接口編程。定義了LogException異常,該異常是日志功能的專屬異常,如果你有看過mybatis其他源碼的話,不難發(fā)現(xiàn),其他功能也定義專屬異常,比如:DataSourceException等,這是mybatis的慣用手法,主要是為了將異常細粒度的劃分,以便更快定位問題。此外,它還定義了LogFactory日志工廠,以便于屏蔽日志工具實例的創(chuàng)建細節(jié),讓用戶使用起來更簡單。

如果是你該如何設計這個功能?

我們按照上面目錄結構的介紹其實已經有一些思路:

  1. 定義一個 Log接口,以便于統(tǒng)一抽象日志功能,這8種日志功能都實現(xiàn) Log接口,并且重寫日志打印方法。
  2. 定義一個 LogFactory日志工廠,它會根據(jù)我們項目中引入的某個日志打印工具jar包,創(chuàng)建一個具體的日志打印工具實例。

看起來,不錯。但是,再仔細想想,LogFactory中如何判斷項目中引入了某個日志打印工具jar包才創(chuàng)建相應的實例呢?我們第一個想到的可能是用if...else判斷不就行了,再想想感覺用if...else不好,7種條件判斷太多了,并非優(yōu)雅的編程。這時候,你會想一些避免太長if...else判斷的方法,當然如果你看過我之前寫的文章《實戰(zhàn)|如何消除又臭又長的if...else判斷更優(yōu)雅的編程?》,可能已經學到了幾招,但是mybatis卻用了一個新的辦法。

mybatis是如何設計這個功能的?

  1. Log接口開始

mybatis日志功能是如何設計的?它里面抽象了日志打印的5種方法和2種判斷方法。

  1. 再分析 LogFactory的代碼
mybatis日志功能是如何設計的?

它里面定義了一個靜態(tài)的構造器logConstructor,沒有用if...else判斷,在static代碼塊中調用了6個tryImplementation方法,該方法會啟動一個執(zhí)行任務去調用了useXXXLogging方法,創(chuàng)建日志打印工具實例。

mybatis日志功能是如何設計的?

當然tryImplementation方法在執(zhí)行前會判斷構造器logConstructor為空才允許執(zhí)行任務中的run方法。下一步看看useXXXLogging方法:mybatis日志功能是如何設計的?看到這里,聰明的你可能會有這樣的疑問,從上圖可以看出mybatis定義了8種useXXXLogging方法,但是在前面的static靜態(tài)代碼塊中卻只調用了6種,這是為什么?

對比后發(fā)現(xiàn):useCustomLogginguseStdOutLogging 前面是沒調用的。useStdOutLogging它里面使用了StdOutImpl

mybatis日志功能是如何設計的?該類其實就是通過JDK自帶的System類的方法打印日志的,無需引入額外的jar包,所以不參與static代碼塊中的判斷。

useCustomLogging方法需要傳入一個實現(xiàn)了Log接口的類,如果mybatis默認提供的6種日志打印工具不滿足要求,以便于用戶自己擴展。

而這個方法是在Configuration類中調用的,如果用戶有自定義logImpl參數(shù)的話。mybatis日志功能是如何設計的?

mybatis日志功能是如何設計的?

具體是在XMLConfigBuilder類的settingsElement方法中調用mybatis日志功能是如何設計的?

再回到前面LogFactorysetImplementation方法

mybatis日志功能是如何設計的?

它會先找到實現(xiàn)了Log接口的類的構造器,返回將該構造器賦值給全局的logConstructor。

這樣一來,就可以通過getLog方法獲取到Log實例。

mybatis日志功能是如何設計的?

然后在業(yè)務代碼中通過下面這種方式獲取Log對象,調用它的方法打印日志了。

mybatis日志功能是如何設計的?

梳理一下LogFactory的流程:

  • 在static代碼塊中根據(jù)逐個引入日志打印工具jar包中的日志類,先判斷如果全局變量logConstructor為空,則加載并獲取相應的構造器,如果可以獲取到則賦值給全局變量logConstructor。
  • 如果全局變量logConstructor不為空,則不繼續(xù)獲取構造器。
  • 根據(jù)getLog方法獲取Log實例
  • 通過Log實例的具體日志方法打印日志

在這里還分享一個知識點,如果某個工具類里面都是靜態(tài)方法,那么要把該工具類的構造方法定義成private的,防止被疑問調用,LogFactory就是這么做的。

mybatis日志功能是如何設計的?
  1. 適配器模式

日志模塊除了使用工廠模式之外,還是有了適配器模式。

適配器模式會將所需要適配的類轉換成調用者能夠使用的目標接口

涉及以下幾個角色:

  • 目標接口( Target )
  • 需要適配的類( Adaptee )
  • 適配器( Adapter)

mybatis日志功能是如何設計的?mybatis是怎么用適配器模式的?

mybatis日志功能是如何設計的?上圖中標紅的類對應的是Adapter角色,LogTarget角色。

mybatis日志功能是如何設計的?LogFactory就是Adaptee,它里面的getLog方法里面包含是需要適配的對象。

sql執(zhí)行日志打印原理

從上面已經能夠確定使用哪種日志打印工具,但在sql執(zhí)行的過程中是如何打印日志的呢?這就需要進一步分析logging目錄下的jdbc目錄了。

mybatis日志功能是如何設計的?

看看這幾個類的關系圖:mybatis日志功能是如何設計的?

ConnectionLogger、PreparedStatementLoggerResultSetLoggerStatementLogger都繼承了BaseJdbcLogger類,并且實現(xiàn)了InvocationHandler接口。從類名非常直觀的看出,這4種類對應的數(shù)據(jù)庫jdbc功能。

類名 對應功能
ConnectionLogger Connection
PreparedStatementLogger PreparedStatement
ResultSetLogger ResultSet
StatementLogger Statement

它們實現(xiàn)了InvocationHandler接口意味著它用到了動態(tài)代理,真正起作用的是invoke方法,我們以ConnectionLogger為例:

mybatis日志功能是如何設計的?

如果調用了prepareStatement方法,則會打印debug日志。

mybatis日志功能是如何設計的?上圖中傳入的original參數(shù)里面包含了\n\t等分隔符,需要將分隔符替換成空格,拼接成一行sql。

最終會在日志中打印sql、入?yún)⒑陀绊懶袛?shù):

mybatis日志功能是如何設計的?上圖中的sql語句是在ConnectionLogger類中打印的

那么入?yún)⒑陀绊懶袛?shù)呢?

入?yún)⒃赑reparedStatementLogger類中打印的

mybatis日志功能是如何設計的?影響行數(shù)在ResultSetLogger類中打印的

mybatis日志功能是如何設計的?
大家需要注意的一個地方是: sql、入?yún)⒑陀绊懶袛?shù)只打印了debug級別的日志,其他級別并沒打印。所以需要在 mybatis 配置文件中的 logging.level 參數(shù)配置成 debug,才能打印日志。

彩蛋

不知道大家有沒有發(fā)現(xiàn)這樣一個問題:

LogFactory的代碼中定義了很多匿名的任務執(zhí)行器

mybatis日志功能是如何設計的?

但是在實際調用時,卻沒有在線程中執(zhí)行,而是直接調用的,這是為什么?

mybatis日志功能是如何設計的?

答案是為了保證順序執(zhí)行,如果所有的日志工具jar包都有,加載優(yōu)先級是:slf4jcommonsLoglog4j2log4jjdkLogNoLog

還有個問題,順序執(zhí)行就可以了,為什么要把匿名內部類定義成Runnable的呢?

這里非常有迷惑性,因為它沒創(chuàng)建Thread類,并不會多線程執(zhí)行。我個人認為,這里是mybatis的開發(fā)者的一種偷懶,不然需要定義一個新類代替這種執(zhí)行任務的含義,還不如就用已有的。

特別推薦一個分享架構+算法的優(yōu)質內容,還沒關注的小伙伴,可以長按關注一下:

mybatis日志功能是如何設計的?

mybatis日志功能是如何設計的?

mybatis日志功能是如何設計的?

長按訂閱更多精彩▼

mybatis日志功能是如何設計的?

如有收獲,點個在看,誠摯感謝

免責聲明:本文內容由21ic獲得授權后發(fā)布,版權歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內容真實性等。需要轉載請聯(lián)系該專欄作者,如若文章內容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: 驅動電源

在工業(yè)自動化蓬勃發(fā)展的當下,工業(yè)電機作為核心動力設備,其驅動電源的性能直接關系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護是驅動電源設計中至關重要的兩個環(huán)節(jié),集成化方案的設計成為提升電機驅動性能的關鍵。

關鍵字: 工業(yè)電機 驅動電源

LED 驅動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設備的使用壽命。然而,在實際應用中,LED 驅動電源易損壞的問題卻十分常見,不僅增加了維護成本,還影響了用戶體驗。要解決這一問題,需從設計、生...

關鍵字: 驅動電源 照明系統(tǒng) 散熱

根據(jù)LED驅動電源的公式,電感內電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關鍵字: LED 設計 驅動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產業(yè)的重要發(fā)展方向。電動汽車的核心技術之一是電機驅動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機驅動系統(tǒng)中的關鍵元件,其性能直接影響到電動汽車的動力性能和...

關鍵字: 電動汽車 新能源 驅動電源

在現(xiàn)代城市建設中,街道及停車場照明作為基礎設施的重要組成部分,其質量和效率直接關系到城市的公共安全、居民生活質量和能源利用效率。隨著科技的進步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關鍵字: 發(fā)光二極管 驅動電源 LED

LED通用照明設計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關鍵字: LED 驅動電源 功率因數(shù)校正

在LED照明技術日益普及的今天,LED驅動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關鍵字: LED照明技術 電磁干擾 驅動電源

開關電源具有效率高的特性,而且開關電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機重量也有所下降,所以,現(xiàn)在的LED驅動電源

關鍵字: LED 驅動電源 開關電源

LED驅動電源是把電源供應轉換為特定的電壓電流以驅動LED發(fā)光的電壓轉換器,通常情況下:LED驅動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: LED 隧道燈 驅動電源
關閉