欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

MyBatis源碼分析之日志logging詳解

 更新時間:2019年03月04日 08:37:34   作者:魏晉秋  
這篇文章主要給大家介紹了關(guān)于MyBatis源碼分析之日志logging的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧

前言

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

logging 配置加載

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

private void loadCustomLogImpl(Properties props) {
 // 從 MyBatis 的 TypeAliasRegistry 中查找 logImpl 鍵所對應(yīng)值的類對象
 // 這里 logImpl 對應(yīng)的 value 值可以從 org.apache.ibatis.session.Configuration 的構(gòu)造方法中找到
 // 注意 Log 類,這是 MyBatis 內(nèi)部對日志對象的抽象
 Class<? extends Log> logImpl = resolveClass(props.getProperty("logImpl"));
 // 將查找到的 Class 對象設(shè)置到 Configuration 對象中
 configuration.setLogImpl(logImpl);
}

很簡單的一個方法,每行都有注釋,其中 configuration.setLogImpl() 里面調(diào)用了 LogFactory.useCustomLogging() ,這出現(xiàn)了新類 LogFactory 類,接下來我們就來聊聊這個類。

LogFactory

useCustomLogging()方法

LogFactory 是框架內(nèi)部獲取 Log 對象的手段,通過它的名字也能看出來。它有如下幾類方法:

// 注意這個類型的方法都是同步方法
public synchronized static useXxxLogging(...);

public static Log getLog(...);

private static tryImplementation(Runnable);

private static setImplementation(Class);

剛剛我們看到被調(diào)用的方法 useCustomLogging() 方法,是用來設(shè)置內(nèi)部使用的日志框架, MyBatis 自身已經(jīng)適配了一些常見的日志框架,如 Slf4j 、 Commons Log 、 Log4j 等等。

useCustomLogging() 方法內(nèi)部調(diào)用 setImplementation(Class) 方法,此方法代碼如下,功能簡單:

private static void setImplementation(Class<? extends Log> implClass) {
 try {
  // 獲取 Log實現(xiàn)類的構(gòu)造方法,它只有一個字符串作為參數(shù)
  Constructor<? extends Log> candidate = implClass.getConstructor(String.class);

  // 創(chuàng)建一個 Log 對象,打印 debug 日志
  Log log = candidate.newInstance(LogFactory.class.getName());
  if (log.isDebugEnabled()) {
   log.debug("Logging initialized using '" + implClass + "' adapter.");
  }

  // ...
  // 把 candidate 對象設(shè)置到 LogFactory 的靜態(tài)變量 logConstructor,這個靜態(tài)變量在 getLog() 方法
  // 中被用到
  logConstructor = candidate;
 } catch (Throwable t) {
  throw new LogException("Error setting Log implementation. Cause: " + t, t);
 }
}

Log 接口

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

Log 接口代碼如下,先試著發(fā)現(xiàn)該接口與其他常見的日志接口的區(qū)別:

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);

}

可有發(fā)現(xiàn)?Log 接口缺少了 info 級別的日志輸出方法,個人猜測應(yīng)該是 MyBatis 內(nèi)部不需要 info 級別的日志輸出,畢竟 Log 接口設(shè)計之初就是為了內(nèi)部使用,而框架使用者是不會采用 MyBatis 的日志作為系統(tǒng)的日志。注意一點: 實現(xiàn)了 Log 接口的類必須擁有一個參數(shù)只有一個字符串的構(gòu)造方法 ,MyBatis 就是通過這個構(gòu)造方法創(chuàng)建日志對象的。

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

public class Log4jImpl implements Log {

 private static final String FQCN = Log4jImpl.class.getName();

 // 這里包裝了 Log4j 框架的日志對象,從而實現(xiàn)適配
 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 類再介紹一下被靜態(tài)代碼塊使用的方法 tryImplementation(Runnable) 。靜態(tài)代碼塊代碼如下:

static {
 // 依次執(zhí)行如下代碼,當(dāng)沒有該類會拋 ClassNotFoundException ,然后繼續(xù)執(zhí)行
 tryImplementation(LogFactory::useSlf4jLogging);
 tryImplementation(LogFactory::useCommonsLogging);
 tryImplementation(LogFactory::useLog4J2Logging);
 tryImplementation(LogFactory::useLog4JLogging);
 tryImplementation(LogFactory::useJdkLogging);
 tryImplementation(LogFactory::useNoLogging);
}

這個方法有點迷惑性,因為它使用 Runnable 接口作為參數(shù),而 useXxxLOgging() 方法又是同步方法,很容易聯(lián)想到多線程,實際上這里并沒有, Runnable 接口不結(jié)合 Thread 類使用它就是一個普通的函數(shù)接口。除去這些就沒什么了,不過是調(diào)用了 Runnable 的 run() 方法而已。

getLog() 方法

getLog() 沒什么多說的,就是通過反射創(chuàng)建 Log 接口實現(xiàn)類,這里沒有使用到緩存,每次調(diào)用都是創(chuàng)建一個新的對象。

jdbc 包

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

除了 BaseJdbcLogger 類其他類都實現(xiàn)了 InvocationHandler 接口,這個接口是 JDK 提供的動態(tài)代理接口,所以顯而易見可以知道它們就是通過代理在各個階段打印相應(yīng)的日志。

以下為 BaseJdbcLogger 類的部分說明:

  • SET_METHODS:靜態(tài)字段,記錄 PreparedStatement 中 set 開頭的的方法名
  • EXECUTE_METHODS:靜態(tài)字段,記錄 SQL 執(zhí)行的方法名
  • columnXxx:實例字段,記錄 SQL 參數(shù)信息
  • statementLog:日志對象
  • queryStack:查詢棧數(shù)
  • getParameterValueString():將 SQL 參數(shù)轉(zhuǎn)為一個字符串
  • removeBreakingWhitespace():移除 SQL 中多余的空白字符
  • prefix():獲取前綴 ==>/<==

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

總結(jié)

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

  • 適配器模式
  • 代理模式

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

好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關(guān)文章

  • python中jieba庫(中文分詞庫)使用安裝教程

    python中jieba庫(中文分詞庫)使用安裝教程

    這篇文章主要介紹了python中jieba庫(中文分詞庫)使用安裝教程,jieba庫是通過中文詞庫的方式來識別分詞的。它首先利用一個中文詞庫,通過詞庫計算漢字之間構(gòu)成詞語的關(guān)聯(lián)概率,所以通過計算漢字之間的概率,就可以形成分詞的結(jié)果,需要的朋友可以參考下
    2023-04-04
  • SpringMVC中RequestMapping注解(作用、出現(xiàn)的位置、屬性)

    SpringMVC中RequestMapping注解(作用、出現(xiàn)的位置、屬性)

    這篇文章主要介紹了SpringMVC中RequestMapping注解(作用、出現(xiàn)的位置、屬性),本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-01-01
  • logback的DuplicateMessageFilter日志過濾操作源碼解讀

    logback的DuplicateMessageFilter日志過濾操作源碼解讀

    這篇文章主要為大家介紹了logback的DuplicateMessageFilter日志過濾操作源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-11-11
  • Java內(nèi)存模型可見性問題相關(guān)解析

    Java內(nèi)存模型可見性問題相關(guān)解析

    這篇文章主要介紹了Java內(nèi)存模型可見性問題相關(guān)解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-12-12
  • Java編程訪問權(quán)限的控制代碼詳解

    Java編程訪問權(quán)限的控制代碼詳解

    這篇文章主要介紹了Java編程訪問權(quán)限的控制代碼詳解,涉及包名,公共的和私有的等相關(guān)內(nèi)容,分享了相關(guān)代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下
    2018-01-01
  • 你要知道IDEA的這些必備插件

    你要知道IDEA的這些必備插件

    這篇文章主要介紹了你要知道IDEA的這些必備插件,文中有非常詳細的圖文示例及代碼,對正在使用IDEA的小伙伴們有很好的幫助喲,需要的朋友可以參考下
    2021-05-05
  • java中List分頁的幾種方法介紹

    java中List分頁的幾種方法介紹

    大家好,本篇文章主要講的是java中List分頁的幾種方法介紹,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • MyBatis-Plus Generator配置詳解

    MyBatis-Plus Generator配置詳解

    這篇文章主要介紹了MyBatis-Plus Generator配置詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • Java設(shè)計模式UML之類圖精解

    Java設(shè)計模式UML之類圖精解

    在UML類圖中,類使用包含類名、屬性(field) 和方法(method) 且?guī)в蟹指罹€的矩形來表示,比如下圖表示一個Employee類,它包含name,age和email這3個屬性,以及modifyInfo()方法
    2022-02-02
  • Java計算球從100米高度自由落下問題

    Java計算球從100米高度自由落下問題

    這篇文章主要介紹了Java球從100米高度自由落下問題,需要的朋友可以參考下
    2017-02-02

最新評論