Mybatis源碼日志模塊分析

看源碼需要先下載源碼,可以去Mybatis的github上的倉庫進行下載,Mybatis

這次就先整理一下日志這一塊的源碼分析,這塊相對來說比較簡單而且這個模塊是Mybatis的基礎模塊。

之前的文章有談到過Java的日志實現,大家也可以參考一下:日志實現以及使用

我這里看的是目前最新的版本:3.5.7版本。

設計模式

我們先來談談這個模塊用到的設計模式。

在市面上有第三方日志實現,但是Mybatis總不可能將每個第三方日志組件實現都做一遍單獨的接入,所以日志用到的模式叫適配器模式。

適配器模式(Adapter Pattern)

是作為兩個不兼容的接口之間的橋梁。這種類型的設計模式屬于結構型模式,它結合了兩個獨立接口的功能。

借用一下網上的UML:

Target:目標角色,即期待得到的接口。

Adaptee:適配者角色,被適配的接口(第三方日志接口)。

Adapter:適配器角色,將被適配接口與目標接口進行橋接。

適用場景:當調用雙方都不太容易修改的時候,為了復用現有組件可以使用適配器模式;在系統中接入第三方組 件的時候經常被使用到;

注意:如果系統中存在過多的適配器,會增加系統的復雜性,設計人員應考慮對系統進行重構;

代理模式(Proxy Pattern)

一個類代表另一個類的功能。這種類型的設計模式屬于結構型模式。

在代理模式中,我們創建具有現有對象的對象,以便向外界提供功能接口。

在Mybatis中日志模塊用到的代理模式使用將查詢的參數,結果以及SQL語句進行打印。

源碼解析

在源碼中org.apache.ibatis.logging包下

Mybatis并沒有實現自己的日志接口,但是MyBatis統一提供了trace、debug、warn、error四個級別;只是定義了一個接口Log,一個適配日志工廠LogFactory;

在LogFactory的靜態代碼塊中,調用的方法順序為:slf4j -> commons-logging -> log4j2 -> log4j -> JDKLogging -> NoLogging。

所以在沒有指定Mybatis的日志類型的時候,會去按照這個順序自動查找對應的第三方日志組件的實現。

package org.apache.ibatis.logging;/*** @author Clinton Begin*/
public interface Log {boolean isDebugEnabled();boolean isTraceEnabled();void error(String s, Throwable e);void error(String s);void debug(String s);void trace(String s);void warn(String s);}
package org.apache.ibatis.logging;import java.lang.reflect.Constructor;public final class LogFactory {public static final String MARKER = "MYBATIS";private static Constructor<? extends Log> logConstructor;static {tryImplementation(LogFactory::useSlf4jLogging);tryImplementation(LogFactory::useCommonsLogging);tryImplementation(LogFactory::useLog4J2Logging);tryImplementation(LogFactory::useLog4JLogging);tryImplementation(LogFactory::useJdkLogging);tryImplementation(LogFactory::useNoLogging);}private LogFactory() {// disable construction}public static Log getLog(Class<?> clazz) {return getLog(clazz.getName());}public static Log getLog(String logger) {try {return logConstructor.newInstance(logger);} catch (Throwable t) {throw new LogException("Error creating logger for logger " + logger + ".  Cause: " + t, t);}}public static synchronized void useCustomLogging(Class<? extends Log> clazz) {setImplementation(clazz);}public static synchronized void useSlf4jLogging() {setImplementation(org.apache.ibatis.logging.slf4j.Slf4jImpl.class);}public static synchronized void useCommonsLogging() {setImplementation(org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl.class);}public static synchronized void useLog4JLogging() {setImplementation(org.apache.ibatis.logging.log4j.Log4jImpl.class);}public static synchronized void useLog4J2Logging() {setImplementation(org.apache.ibatis.logging.log4j2.Log4j2Impl.class);}public static synchronized void useJdkLogging() {setImplementation(org.apache.ibatis.logging.jdk14.Jdk14LoggingImpl.class);}public static synchronized void useStdOutLogging() {setImplementation(org.apache.ibatis.logging.stdout.StdOutImpl.class);}public static synchronized void useNoLogging() {setImplementation(org.apache.ibatis.logging.nologging.NoLoggingImpl.class);}private static void tryImplementation(Runnable runnable) {if (logConstructor == null) {try {runnable.run();} catch (Throwable t) {// ignore}}}private static void setImplementation(Class<? extends Log> implClass) {try {Constructor<? extends Log> candidate = implClass.getConstructor(String.class);Log log = candidate.newInstance(LogFactory.class.getName());if (log.isDebugEnabled()) {log.debug("Logging initialized using '" + implClass + "' adapter.");}logConstructor = candidate;} catch (Throwable t) {throw new LogException("Error setting Log implementation.  Cause: " + t, t);}}}

我們就拿一個示例講解:Log4j

我們找到Log4j的適配器調用的類,如下

其他類型的日志組件適配都是以這種形式進行編碼的。

第三方的日志組件已經適配好,接下來就是將查詢過程的各項參數結果集打印。

都知道所有的ORM框架底層都是采用JDBC做查詢的,Mybatis也不例外。

這里就必須用到了代理模式,Mybatis的代理模式是通過JDK的動態代理進行實現的之前講AOP時講過這個;AOP代理及實現

在Mybatis中查詢SQL主要是由Exceutor去查詢的,默認使用SimpleExecutor,

我們進去這個getConnection方法

這個newInstance方法里面是通過JDK動態代理進行創建的

  public static Connection newInstance(Connection conn, Log statementLog, int queryStack) {InvocationHandler handler = new ConnectionLogger(conn, statementLog, queryStack);ClassLoader cl = Connection.class.getClassLoader();return (Connection) Proxy.newProxyInstance(cl, new Class[]{Connection.class}, handler);}

所以在拿到Connection鏈接之后,需創建一個Statement對象,所以在創建的時候,就會進入到invoke方法

這樣依次進行代理,在使用ResultSet的時候也會進入到對應的代理對象當中

這樣日志打印的過程就是這樣的,

具體的日志類型加載后面會講,日志模塊分析就差不多這樣講完了。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/537131.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/537131.shtml
英文地址,請注明出處:http://en.pswp.cn/news/537131.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python手機端給電腦端發送數據_期貨交易軟件有哪些比較好用?分手機端和電腦端...

一、電腦端交易軟件期貨電腦端交易軟件目前市場上用的最多的是文華財經和博易大師&#xff0c;這兩個軟件都是免費交易使用的。從投資者使用角度來看&#xff0c;目前電腦端文華財經的評價比博易大師高一些。當然每個投資者有自己的使用習慣&#xff0c;博易大師也有自己優點&a…

Find the Difference(leetcode389)

2019獨角獸企業重金招聘Python工程師標準>>> Given two strings s and t which consist of only lowercase letters. String t is generated by random shuffling string s and then add one more letter at a random position. Find the letter that was added in …

Mybatis源碼之數據源模塊分析

先來看看java純jdbc查詢數據的示例&#xff1a; try {//加載對應的驅動類Class.forName("com.mysql.cj.jdbc.Driver");//創建連接Connection connection DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?serverTimezoneUTC", "roo…

reactnative 獲取定位_[RN] React Native 獲取地理位置

import React, {Component} from react;import {StyleSheet, Text, View}from react-native;exportdefault classTestGeo extends Component {state{longitude:,//經度latitude: ,//緯度city: ,district:,street:,position:,//位置名稱};componentWillMount () >{this.getPo…

第二沖刺階段第三天

查閱資料&#xff0c;修改控件界面轉載于:https://www.cnblogs.com/gyy0/p/10066452.html

Mybatis源碼之緩存模塊分析

緩存這個東西在很多應用中都能看到它們的身影&#xff0c;這次就講講在Mybatis中的緩存是怎么應用的&#xff0c;雖然說吧Mybatis中的緩存基本不怎么用&#xff0c;用的更多是第三方組件redis、MongoDB、MemCache等等。 Mybatis的緩存是基于Map實現的&#xff0c;從緩存中讀寫…

Mybatis源碼之核心流程分析

終于談到了Mybatis最核心的東西了&#xff0c;最核心的就是通過配置XML文件或注解中的SQL&#xff0c;直接調用接口就能執行配置好的SQL語句并封裝成對應的返回類型的數據。 先看一下Mybatis使用示例&#xff1a; //創建Builder對象 SqlSessionFactoryBuilder builder new S…

mimakatz用法_兩步完成利用procdump64+mimikatz獲取win用戶密碼

使用procdump64mimikatz可實現從內存中獲取明文密碼工具鏈接&#xff1a;https://pan.baidu.com/s/1gNc9qLcNSNBohIVrAiqShw 密碼&#xff1a;fc38首先得先獲取到內存文件lsass.exe進程, 它用于本地安全和登陸策略,一般在進程管理器中能看到, 比如這樣1.導出lsass.exeprocdump6…

ios app提交之前需要哪幾個證書

1、遇到的問題 一款App在別人的機器上開發和發布&#xff0c;現在迭代更新和開發需要在一臺新mac機上開發和發布。&#xff08;使用同一個開發者賬號&#xff09;問題&#xff1a; 1.在新mac機器上開發并導入真機測試&#xff0c;是不是需要從別人的機器上面導處開發者證書、開…

Mybatis源碼之與Spring集成包

這次講講Mybatis與Spring的整合&#xff0c;作為兩款優秀的開源框架&#xff0c;被大眾廣泛使用&#xff0c;自然是需要強強聯合的。 使用示例 先看一下怎么使用&#xff0c;首先需要引用這兩款框架的jar包&#xff1a; <dependency>//spring-webmvc會自動去引入其他S…

hadoop主節點切換_hadoop2.0 HA的主備自動切換

在《hadoop2.0 QJM方式的HA的配置》一文中介紹了HA的配置&#xff0c;是通過手工進行主備切換的。本文在這基礎上&#xff0c;繼續介紹HA的主備自動切換(automatic failover)的配置。自動切換是通過配置zookeeper來實現的&#xff0c;關于zookeeper的安裝和配置&#xff0c;在這…

Mybatis源碼之插件模塊分析

總結完這個Mybatis的整體主要功能基本上就差不多完&#xff0c;還有一些細節的部分&#xff0c;后續都會記錄補充。 插件這個東西一般用的比較少&#xff0c;就算用的多的插件也算是PageHelper分頁插件&#xff1b; PageHelper官網&#xff1a;https://github.com/pagehelper…

AMD推出7nm高端顯卡Radeon VII,直指英偉達RTX 2080

顯卡戰爭已經發展到了2019年&#xff0c;并且變得比任何人預想的都要激烈。 CES 2019大會上&#xff0c;AMD發布了第一款消費級的 7nm GPU&#xff0c;取名&#xff1a;Radeon VII。據了解&#xff0c;這不是 AMD 的第一顆 7nm 處理器&#xff08;早期以 AI 運算為主的 Radeon …

電子繪本pdf_【孩子必看的】20本世界著名英文繪本 | PDF電子版+MP3音頻

原標題&#xff1a;【孩子必看的】20本世界著名英文繪本 | PDF電子版MP3音頻2 —6歲年齡段的孩子&#xff0c;自我意識逐漸萌芽&#xff0c;已經明白書是一種“特殊”的玩具&#xff0c;不在撕書、咬書、把書搬來搬去。這個階段他們記憶力超強&#xff0c;唐詩、三字經啥的&…

Spring集成Mybatis多數據源配置

既然在整理Mybatis那就把經常用的這個多數據源的筆記也整一下吧。 Spring集成Mybatis在之前就已經提到了。Spring集成Mybatis 集成Mybatis多數據源有兩種方式&#xff1a; 1、創建多個SqlSessionFactory&#xff0c;掃描每個SqlSessionFactoryBean對應的包&#xff0c;形成了…

Spring文件上傳

2019獨角獸企業重金招聘Python工程師標準>>> Spring文件上傳 1、所需依賴包&#xff1a;commons-fileupload-1.3.1.jar2、Maven配置文件pom.xml文件中加入依賴Jar包<dependency><groupId>commons-fileupload</groupId><artifactId>commons-…

中英離線翻譯mac_Instant Translate for Mac-即時翻譯Mac版下載 V1.3.0-PC6蘋果網

即時翻譯(Instant Translate)Mac版是一款Mac平臺的翻譯及辭典軟件&#xff0c;Instant Translate支持90的語言互翻譯&#xff0c;通過ControlS切換語言&#xff0c;并且支持發音功能&#xff0c;并且支持自動檢測語言并進行翻譯。軟件特色Instant Translate的主要特點&#xff…

基于Zookeeper使用ZkClient實現分布式鎖

有段時間沒寫博客了&#xff0c;在整理之前寫過的一套自定義框架&#xff0c;并且整理好上傳值github上了&#xff0c;也有一些新功能還在開發&#xff0c;歡迎大家使用&#xff1a;一個好用的Http接口請求工具組件 可能今天這篇文章跟之前的比有些跳躍性&#xff0c;一下子就…

算法題學到的一些小語言細節

1.要學會用i&#xff1b;可以簡化很多代碼&#xff1a;i&#xff1b;copyFromMe(i)&#xff1b;可以寫成&#xff1a;copyFromeMe(i) 2.StringBuffer也跟列表一樣有append函數&#xff1b; 3.if語句是分支不能進行循環&#xff0c;要寫成while才能替代循環里面的判斷 4. 這里的…

android 按鈕帶圖標 陰影_android中帶圖標的按鈕(ImageButton)怎么用

展開全部除了Android系統自帶的Button按鈕以外&#xff0c;還提供了帶圖標的按鈕ImageButton要制作帶圖標的按鈕&#xff0c;首先要在布局62616964757a686964616fe58685e5aeb931333337613163文件中定義ImageButton&#xff0c;然后通過setImageDrawable方法來設置要顯示的圖標。…