SLF4J & Logback 初始化過程分析

淵源

Logback 為log4j作者推出又一個日志框架我纪,更好的實現(xiàn)了slf4j規(guī)范吩案。
SLF4J 全稱 Simple Logging Facade for Java。Facade 是一種設(shè)計模式虚吟,中文的一種翻譯叫做 門面模式羔挡,可以類比為那句經(jīng)典的,沒有問題是加一層所不能解決的(大意伍茄,原話記不清了栋盹。。敷矫。例获。)』龋總結(jié)起來講就是slf4j本身并沒有提供日志記錄的功能躏敢,僅僅是提供一個標(biāo)準(zhǔn),具體的功能實現(xiàn)由具體的日志框架實現(xiàn)整葡。詳細(xì)的介紹見鏈接 https://www.slf4j.org/

環(huán)境設(shè)置

  • 示例編輯環(huán)境使用idea
  • 日志實現(xiàn)框架采用 logback
  • 依賴管理采用maven
    <dependencies>
      <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-api</artifactId>
          <version>1.7.5</version>
      </dependency>
      <dependency>
          <groupId>ch.qos.logback</groupId>
          <artifactId>logback-classic</artifactId>
          <version>1.2.3</version>
      </dependency>
    </dependencies>
    

源碼分析

示例代碼如下

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Slf4jTest {
    private static final Logger logger = LoggerFactory.getLogger(Slf4jTest.class);
    
    public static void main(String[] args) {
        logger.info("slf4j");
    }
}

代碼分析

//日志打印件余,日志功能實現(xiàn),本次分析重點是初始化過程遭居,并非具體日志打印功能實現(xiàn)
logger.info("slf4j");

//變量的初始化部分啼器,本文關(guān)注的重點部分
private static final Logger logger = LoggerFactory.getLogger(Slf4jTest.class);

LoggerFactory.getLogger 方法一步步點進(jìn)去(ctrl+alt+b,如果出現(xiàn)多個實現(xiàn)類的情況俱萍,則選擇包名包含logback的進(jìn)入)直到

/**
   * Return a logger named according to the name parameter using the statically
   * bound {@link ILoggerFactory} instance.
   *
   * @param name The name of the logger.
   * @return logger
   */
  public static Logger getLogger(String name) {
    ILoggerFactory iLoggerFactory = getILoggerFactory();
    return iLoggerFactory.getLogger(name);
  }

發(fā)現(xiàn)出現(xiàn)一個Factory方法(getILoggerFactory)端壳,開始重點分析該方法實現(xiàn),查看getILoggerFactory方法實現(xiàn)枪蘑,代碼如下:

  /**
   * Return the {@link ILoggerFactory} instance in use.
   * <p/>
   * <p/>
   * ILoggerFactory instance is bound with this class at compile time.
   *
   * @return the ILoggerFactory instance in use
   */
  public static ILoggerFactory getILoggerFactory() {
    if (INITIALIZATION_STATE == UNINITIALIZED) {
      INITIALIZATION_STATE = ONGOING_INITIALIZATION;
      performInitialization();
    }
    switch (INITIALIZATION_STATE) {
      case SUCCESSFUL_INITIALIZATION:
        return StaticLoggerBinder.getSingleton().getLoggerFactory();
      case NOP_FALLBACK_INITIALIZATION:
        return NOP_FALLBACK_FACTORY;
      case FAILED_INITIALIZATION:
        throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG);
      case ONGOING_INITIALIZATION:
        // support re-entrant behavior.
        // See also http://bugzilla.slf4j.org/show_bug.cgi?id=106
        return TEMP_FACTORY;
    }
    throw new IllegalStateException("Unreachable code");
  }

開始分析getILoggerFactory方法损谦,先拋出以下問題:

  1. INITIALIZATION_STATE 初始化的位置在哪?初始狀態(tài)是什么岳颇?值是在哪里進(jìn)行更新的照捡?
  2. FAILED_INITIALIZATION , SUCCESSFUL_INITIALIZATION 等在哪里定義?都有哪些话侧?含義是什么栗精?
  3. performInitialization 方法執(zhí)行了哪些操作?
  4. NOP_FALLBACK_FACTORY , TEMP_FACTORY 又是什么東西?
  5. StaticLoggerBinder.getSingleton().getLoggerFactory(); 這句代碼做了什么見不得人的事情悲立?

1.INITIALIZATION_STATE 初始化的位置在哪鹿寨?初始狀態(tài)是什么?值是在哪里進(jìn)行更新的薪夕?

  static int INITIALIZATION_STATE = UNINITIALIZED;

可以看出來 變量 INITIALIZATION_STATE 初始值為 UNINITIALIZED脚草,字面含義是未被初始化狀態(tài)。getILoggerFactory方法首先進(jìn)行判斷寥殖,如果 INITIALIZATION_STATE 值為 未初始化狀體玩讳,先設(shè)置INITIALIZATION_STATE 狀態(tài)為 初始化進(jìn)行中狀態(tài)(ONGOING_INITIALIZATION ),然后執(zhí)行具體初始化操作嚼贡,猜測在performInitialization()方法執(zhí)行的過程中很有可能更新該值的操作。

2. FAILED_INITIALIZATION , SUCCESSFUL_INITIALIZATION 等在哪里定義同诫,含義是什么粤策?都有哪些?

  static final int UNINITIALIZED = 0;
  static final int ONGOING_INITIALIZATION = 1;
  static final int FAILED_INITIALIZATION = 2;
  static final int SUCCESSFUL_INITIALIZATION = 3;
  static final int NOP_FALLBACK_INITIALIZATION = 4;

很明顯這些類型的變量的創(chuàng)建是為了標(biāo)識 工廠 初始化狀態(tài)使用的误窖,定義位置在LogFactory 類中叮盘,含義分別為(自上至下) 未被初始化,初始化進(jìn)行中霹俺,初始化失敗柔吼,初始化成功,NOP_FALLBACK_INITIALIZATION(no operation fallback initialization,這個不知道怎么翻譯比較好)丙唧。

3.performInitialization 方法執(zhí)行了哪些操作愈魏?

  • 首先看performInitialization 方法實現(xiàn)
private final static void performInitialization() {
    bind();
    if (INITIALIZATION_STATE == SUCCESSFUL_INITIALIZATION) {
      versionSanityCheck();
    }
  }
  • 追蹤bind方法實現(xiàn)
private final static void bind() {
    try {
      Set staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet();
      reportMultipleBindingAmbiguity(staticLoggerBinderPathSet);
      // the next line does the binding
      StaticLoggerBinder.getSingleton();
      INITIALIZATION_STATE = SUCCESSFUL_INITIALIZATION;
      reportActualBinding(staticLoggerBinderPathSet);
      emitSubstituteLoggerWarning();
    } catch (NoClassDefFoundError ncde) {
      String msg = ncde.getMessage();
      if (messageContainsOrgSlf4jImplStaticLoggerBinder(msg)) {
        INITIALIZATION_STATE = NOP_FALLBACK_INITIALIZATION;
        Util.report("Failed to load class \"org.slf4j.impl.StaticLoggerBinder\".");
        Util.report("Defaulting to no-operation (NOP) logger implementation");
        Util.report("See " + NO_STATICLOGGERBINDER_URL
                + " for further details.");
      } else {
        failedBinding(ncde);
        throw ncde;
      }
    } catch (java.lang.NoSuchMethodError nsme) {
      String msg = nsme.getMessage();
      if (msg != null && msg.indexOf("org.slf4j.impl.StaticLoggerBinder.getSingleton()") != -1) {
        INITIALIZATION_STATE = FAILED_INITIALIZATION;
        Util.report("slf4j-api 1.6.x (or later) is incompatible with this binding.");
        Util.report("Your binding is version 1.5.5 or earlier.");
        Util.report("Upgrade your binding to version 1.6.x.");
      }
      throw nsme;
    } catch (Exception e) {
      failedBinding(e);
      throw new IllegalStateException("Unexpected initialization failure", e);
    }
  }

...未完待續(xù)
一天寫一點,給自己加油>_<

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末想际,一起剝皮案震驚了整個濱河市培漏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌胡本,老刑警劉巖牌柄,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異侧甫,居然都是意外死亡珊佣,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進(jìn)店門披粟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來咒锻,“玉大人,你說我怎么就攤上這事僻爽〕娴铮” “怎么了?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵胸梆,是天一觀的道長敦捧。 經(jīng)常有香客問我须板,道長,這世上最難降的妖魔是什么兢卵? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任习瑰,我火速辦了婚禮,結(jié)果婚禮上秽荤,老公的妹妹穿的比我還像新娘甜奄。我一直安慰自己,他們只是感情好窃款,可當(dāng)我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布课兄。 她就那樣靜靜地躺著,像睡著了一般晨继。 火紅的嫁衣襯著肌膚如雪烟阐。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天紊扬,我揣著相機與錄音蜒茄,去河邊找鬼。 笑死餐屎,一個胖子當(dāng)著我的面吹牛檀葛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播腹缩,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼屿聋,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了庆聘?” 一聲冷哼從身側(cè)響起胜臊,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎伙判,沒想到半個月后象对,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡宴抚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年勒魔,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片菇曲。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡冠绢,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出常潮,到底是詐尸還是另有隱情弟胀,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站孵户,受9級特大地震影響萧朝,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜夏哭,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一检柬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧竖配,春花似錦何址、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至胁镐,卻和暖如春项钮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背希停。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留署隘,地道東北人宠能。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像磁餐,于是被迫代替她去往敵國和親违崇。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,435評論 2 359

推薦閱讀更多精彩內(nèi)容