最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MyBatis源碼分析之日志logging詳解

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

前言

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

logging 配置加載

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

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

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

LogFactory

useCustomLogging()方法

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

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

public static Log getLog(...);

private static tryImplementation(Runnable);

private static setImplementation(Class);

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

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

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

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

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

Log 接口

剛剛我們接觸到了 Log 這個(gè)類,它是一個(gè)接口,是 MyBatis 內(nèi)部使用的日志對(duì)象的抽象,它是為了兼容市面上各種各樣的日志框架,使用了適配器模式,通過(guò) Log 接口來(lái)連接 MyBatis 和其他日志框架,通過(guò)實(shí)現(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 級(jí)別的日志輸出方法,個(gè)人猜測(cè)應(yīng)該是 MyBatis 內(nèi)部不需要 info 級(jí)別的日志輸出,畢竟 Log 接口設(shè)計(jì)之初就是為了內(nèi)部使用,而框架使用者是不會(huì)采用 MyBatis 的日志作為系統(tǒng)的日志。注意一點(diǎn): 實(shí)現(xiàn)了 Log 接口的類必須擁有一個(gè)參數(shù)只有一個(gè)字符串的構(gòu)造方法 ,MyBatis 就是通過(guò)這個(gè)構(gòu)造方法創(chuàng)建日志對(duì)象的。

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

public class Log4jImpl implements Log {

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

 // 這里包裝了 Log4j 框架的日志對(duì)象,從而實(shí)現(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)沒(méi)有該類會(huì)拋 ClassNotFoundException ,然后繼續(xù)執(zhí)行
 tryImplementation(LogFactory::useSlf4jLogging);
 tryImplementation(LogFactory::useCommonsLogging);
 tryImplementation(LogFactory::useLog4J2Logging);
 tryImplementation(LogFactory::useLog4JLogging);
 tryImplementation(LogFactory::useJdkLogging);
 tryImplementation(LogFactory::useNoLogging);
}

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

getLog() 方法

getLog() 沒(méi)什么多說(shuō)的,就是通過(guò)反射創(chuàng)建 Log 接口實(shí)現(xiàn)類,這里沒(méi)有使用到緩存,每次調(diào)用都是創(chuàng)建一個(gè)新的對(duì)象。

jdbc 包

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

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

以下為 BaseJdbcLogger 類的部分說(shuō)明:

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

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

總結(jié)

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

  • 適配器模式
  • 代理模式

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

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

相關(guān)文章

  • Java畢業(yè)設(shè)計(jì)實(shí)戰(zhàn)之寵物醫(yī)院與商城一體的系統(tǒng)的實(shí)現(xiàn)

    Java畢業(yè)設(shè)計(jì)實(shí)戰(zhàn)之寵物醫(yī)院與商城一體的系統(tǒng)的實(shí)現(xiàn)

    這是一個(gè)使用了java+Springboot+Jsp+maven+Mysql開發(fā)的寵物醫(yī)院與商城一體的系統(tǒng),是一個(gè)畢業(yè)設(shè)計(jì)的實(shí)戰(zhàn)練習(xí),具有寵物醫(yī)院和寵物商城該有的所有功能,感興趣的朋友快來(lái)看看吧
    2022-02-02
  • Java的JDBC中Statement與CallableStatement對(duì)象實(shí)例

    Java的JDBC中Statement與CallableStatement對(duì)象實(shí)例

    這篇文章主要介紹了Java的JDBC中Statement與CallableStatement對(duì)象實(shí)例,JDBC是Java編程中用于操作數(shù)據(jù)庫(kù)的API,需要的朋友可以參考下
    2015-12-12
  • 解析SpringCloud簡(jiǎn)介與微服務(wù)架構(gòu)

    解析SpringCloud簡(jiǎn)介與微服務(wù)架構(gòu)

    這篇文章主要介紹了SpringCloud簡(jiǎn)介與微服務(wù)架構(gòu),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01
  • Spring表達(dá)式語(yǔ)言SpEL用法詳解

    Spring表達(dá)式語(yǔ)言SpEL用法詳解

    這篇文章主要介紹了spring表達(dá)式語(yǔ)言SpEL用法詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-01-01
  • 基于Java class對(duì)象說(shuō)明、Java 靜態(tài)變量聲明和賦值說(shuō)明(詳解)

    基于Java class對(duì)象說(shuō)明、Java 靜態(tài)變量聲明和賦值說(shuō)明(詳解)

    下面小編就為大家?guī)?lái)一篇基于Java class對(duì)象說(shuō)明、Java 靜態(tài)變量聲明和賦值說(shuō)明(詳解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-06-06
  • SpringMVC自定義攔截器實(shí)現(xiàn)過(guò)程詳解

    SpringMVC自定義攔截器實(shí)現(xiàn)過(guò)程詳解

    這篇文章主要介紹了SpringMVC自定義攔截器實(shí)現(xiàn)過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05
  • scala 操作數(shù)據(jù)庫(kù)的方法

    scala 操作數(shù)據(jù)庫(kù)的方法

    這篇文章主要介紹了scala 操作數(shù)據(jù)庫(kù)的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • java輸入時(shí)如何通過(guò)回車(enter)來(lái)結(jié)束輸入

    java輸入時(shí)如何通過(guò)回車(enter)來(lái)結(jié)束輸入

    這篇文章主要介紹了java輸入時(shí)如何通過(guò)回車(enter)來(lái)結(jié)束輸入,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • IntelliJ IDEA修改內(nèi)存大小,使得idea運(yùn)行更流暢

    IntelliJ IDEA修改內(nèi)存大小,使得idea運(yùn)行更流暢

    今天小編就為大家分享一篇關(guān)于IntelliJ IDEA修改內(nèi)存大小,使得idea運(yùn)行更流暢的文章,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-10-10
  • Java中如何檢查數(shù)組是否包含某整數(shù)

    Java中如何檢查數(shù)組是否包含某整數(shù)

    這篇文章主要介紹了在?Java?中檢查數(shù)組是否包含某整數(shù),在本文中,我們使用了幾個(gè)內(nèi)置的方法,如anyMatch()、contains()、binarySearch()等,我們將在給定的數(shù)組中找到一個(gè)值,結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-05-05

最新評(píng)論

青田县| 冕宁县| 美姑县| 鄂温| 西吉县| 义乌市| 工布江达县| 秦安县| 淄博市| 小金县| 化州市| 屏东县| 安泽县| 台南市| 阿拉善右旗| 成安县| 银川市| 图片| 五家渠市| 惠安县| 阿巴嘎旗| 福州市| 东辽县| 安徽省| 阿坝| 论坛| 大渡口区| 翁源县| 台中市| 信阳市| 景德镇市| 图片| 兴山县| 广昌县| 金湖县| 师宗县| 涪陵区| 灵寿县| 西宁市| 易门县| 淳安县|