一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - MyBatis源碼分析之日志logging詳解

MyBatis源碼分析之日志logging詳解

2021-07-18 15:46魏晉秋 Java教程

這篇文章主要給大家介紹了關于MyBatis源碼分析之日志logging的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧

前言

本文介紹個人對 logging 包下源碼的理解。分享出來供大家參考學習,下面話不多說了,來一起看看詳細的介紹吧

logging 配置加載

我們先從日志的配置加載開始閱讀, mybatis 的各項配置的加載過程都可以從 xmlconfigbuilder 類中找到,我們定位到該類下的日志加載方法 loadcustomlogimpl:

?
1
2
3
4
5
6
7
8
private void loadcustomlogimpl(properties props) {
 // 從 mybatis 的 typealiasregistry 中查找 logimpl 鍵所對應值的類對象
 // 這里 logimpl 對應的 value 值可以從 org.apache.ibatis.session.configuration 的構造方法中找到
 // 注意 log 類,這是 mybatis 內部對日志對象的抽象
 class<? extends log> logimpl = resolveclass(props.getproperty("logimpl"));
 // 將查找到的 class 對象設置到 configuration 對象中
 configuration.setlogimpl(logimpl);
}

很簡單的一個方法,每行都有注釋,其中 configuration.setlogimpl() 里面調用了 logfactory.usecustomlogging() ,這出現了新類 logfactory 類,接下來我們就來聊聊這個類。

logfactory

usecustomlogging()方法

logfactory 是框架內部獲取 log 對象的手段,通過它的名字也能看出來。它有如下幾類方法:

?
1
2
3
4
5
6
7
8
// 注意這個類型的方法都是同步方法
public synchronized static usexxxlogging(...);
 
public static log getlog(...);
 
private static tryimplementation(runnable);
 
private static setimplementation(class);

剛剛我們看到被調用的方法 usecustomlogging() 方法,是用來設置內部使用的日志框架, mybatis 自身已經適配了一些常見的日志框架,如 slf4j 、 commons log 、 log4j 等等。

usecustomlogging() 方法內部調用 setimplementation(class) 方法,此方法代碼如下,功能簡單:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private static void setimplementation(class<? extends log> implclass) {
 try {
  // 獲取 log實現類的構造方法,它只有一個字符串作為參數
  constructor<? extends log> candidate = implclass.getconstructor(string.class);
 
  // 創建一個 log 對象,打印 debug 日志
  log log = candidate.newinstance(logfactory.class.getname());
  if (log.isdebugenabled()) {
   log.debug("logging initialized using '" + implclass + "' adapter.");
  }
 
  // ...
  // 把 candidate 對象設置到 logfactory 的靜態變量 logconstructor,這個靜態變量在 getlog() 方法
  // 中被用到
  logconstructor = candidate;
 } catch (throwable t) {
  throw new logexception("error setting log implementation. cause: " + t, t);
 }
}

log 接口

剛剛我們接觸到了 log 這個類,它是一個接口,是 mybatis 內部使用的日志對象的抽象,它是為了兼容市面上各種各樣的日志框架,使用了適配器模式,通過 log 接口來連接 mybatis 和其他日志框架,通過實現 log 接口連著 mybatis 和需要適配的日志框架。

log 接口代碼如下,先試著發現該接口與其他常見的日志接口的區別:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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);
 
}

可有發現?log 接口缺少了 info 級別的日志輸出方法,個人猜測應該是 mybatis 內部不需要 info 級別的日志輸出,畢竟 log 接口設計之初就是為了內部使用,而框架使用者是不會采用 mybatis 的日志作為系統的日志。注意一點: 實現了 log 接口的類必須擁有一個參數只有一個字符串的構造方法 ,mybatis 就是通過這個構造方法創建日志對象的。

mybatis 適配了許多常見的日志框架,這里就單單介紹 log4jimpl 類,它代碼非常簡單:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
public class log4jimpl implements log {
 
 private static final string fqcn = log4jimpl.class.getname();
 
 // 這里包裝了 log4j 框架的日志對象,從而實現適配
 private final logger log;
 
 public log4jimpl(string clazz) {
 log = logger.getlogger(clazz);
 }
 
 @override
 public boolean isdebugenabled() {
 return log.isdebugenabled();
 }
 
 @override
 public boolean istraceenabled() {
 return log.istraceenabled();
 }
 
 @override
 public void error(string s, throwable e) {
 log.log(fqcn, level.error, s, e);
 }
 
 @override
 public void error(string s) {
 log.log(fqcn, level.error, s, null);
 }
 
 @override
 public void debug(string s) {
 log.log(fqcn, level.debug, s, null);
 }
 
 @override
 public void trace(string s) {
 log.log(fqcn, level.trace, s, null);
 }
 
 @override
 public void warn(string s) {
 log.log(fqcn, level.warn, s, null);
 }
 
}

tryimplementation() 方法

logfactory 類再介紹一下被靜態代碼塊使用的方法 tryimplementation(runnable) 。靜態代碼塊代碼如下:

?
1
2
3
4
5
6
7
8
9
static {
 // 依次執行如下代碼,當沒有該類會拋 classnotfoundexception ,然后繼續執行
 tryimplementation(logfactory::useslf4jlogging);
 tryimplementation(logfactory::usecommonslogging);
 tryimplementation(logfactory::uselog4j2logging);
 tryimplementation(logfactory::uselog4jlogging);
 tryimplementation(logfactory::usejdklogging);
 tryimplementation(logfactory::usenologging);
}

這個方法有點迷惑性,因為它使用 runnable 接口作為參數,而 usexxxlogging() 方法又是同步方法,很容易聯想到多線程,實際上這里并沒有, runnable 接口不結合 thread 類使用它就是一個普通的函數接口。除去這些就沒什么了,不過是調用了 runnable 的 run() 方法而已。

getlog() 方法

getlog() 沒什么多說的,就是通過反射創建 log 接口實現類,這里沒有使用到緩存,每次調用都是創建一個新的對象。

jdbc 包

這個包與其他包有些不同,它的職能是為各個階段的流程提供日志打印,該包一共就五個類,它們的關系如下:

MyBatis源碼分析之日志logging詳解

除了 basejdbclogger 類其他類都實現了 invocationhandler 接口,這個接口是 jdk 提供的動態代理接口,所以顯而易見可以知道它們就是通過代理在各個階段打印相應的日志。

以下為 basejdbclogger 類的部分說明:

  • set_methods:靜態字段,記錄 preparedstatement 中 set 開頭的的方法名
  • execute_methods:靜態字段,記錄 sql 執行的方法名
  • columnxxx:實例字段,記錄 sql 參數信息
  • statementlog:日志對象
  • querystack:查詢棧數
  • getparametervaluestring():將 sql 參數轉為一個字符串
  • removebreakingwhitespace():移除 sql 中多余的空白字符
  • prefix():獲取前綴 ==>/<==

而其余四個類都是簡單的邏輯:判斷執行的方法是否為指定方法,然后打印相應的日志。

總結

以上便是個人研究 logging 包的內容,本包使用了以下設計模式(包含不限于):

  • 適配器模式
  • 代理模式

其中適配器模式應該是一個比較不錯的示例,可做參考。

好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對服務器之家的支持。

原文鏈接:https://segmentfault.com/a/1190000018365826

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 午夜一区二区福利视频在线 | 色婷婷婷丁香亚洲综合不卡 | 婷综合| a级毛片毛片免费很很综合 a级黄色视屏 | ai换脸杨颖被啪在线观看 | 视频二区 素人 制服 国产 | jizz农村野外jizz农民 | 免费草比视频 | 亚洲天堂网站在线 | 黄色a视频| 久久视热频国产这里只有精品23 | 亚洲成年人免费网站 | 美女被扒开屁股进去网 | 福利国产精品 | 香蕉国产成版人视频在线观看 | 亚洲精品www久久久久久久软件 | 成人影院vs一区二区 | 四虎影视地址 | 精品图区| 日韩网新片免费 | 热久久天天拍天天拍热久久2018 | 视频一区二区三区在线观看 | 国产日韩一区二区 | 日韩欧美不卡视频 | 啪啪无尽3d动漫漫画免费网站 | 婷婷日韩 | 久久se精品一区二区国产 | 亚洲欧美日韩国产精品影院 | 免费一级夫妻a | 激情艳妇之性事高h | 4455四色永久免费 | 毛片免 | 大好硬好深好爽想要视频 | 日本高清色视影www日本 | 国产精品久久久久久久久久久威 | 国自产拍在线天天更新91 | 精品久久久久久午夜 | 国产成人www免费人成看片 | 超兴奋朋友的中文字幕下 | 8x8x丝袜美女| 欧美xxoo做爰猛烈视频 |