目錄
(一)入口:slf4j選擇日志框架
(二)日志框架初始化
(1)logback的3種配置方式
a、BasicConfigurator默認配置
b、SPI方式配置的Configurator實現類
c、通過配置文件初始化
(2)xml配置文件初始化
(三)Logger的創建
(四)打印日志
本文源碼基于:logback版本:1.2.11
在我們使用logback日志框架時,通常都會通過配置logback.xml定制化我們的日志需求。但你是否對loback日志如何加載配置感到好奇?如果沒有logback.xml,logback的默認配置又是什么樣的?配置文件中定義的appender和logger又是什么關系呢?在這一篇章我們會通過深入logback源碼進行分析
(一)入口:slf4j選擇日志框架
logback也是基于slf4j的一個日志框架實現。可以從maven的依賴中可以看到logback-classic依賴了slf4j-api。
所以我們使用logback日志也是使用slf4j的接口:
private static final Logger logger = LoggerFactory.getLogger(LogTest.class);
而日志的配置加載就在首次調用LoggerFactory.getLogger時進行,具體是在LoggerFactory.getLogger-》getILoggerFactory():獲取LoggerFactory時進行初始化,可以看到一個如下的performInitialization()方法。從名字可以看出這個方法就是去執行初始化的,而且使用狀態位保證只初始化一次
我們接著看performInitialization方法中的bind方法:
我們知道slf4j只是定義了日志的接口,是一個日志接口協議。它將具體的日志框架實現交給各個日志框架,比如log4j2、logback等主流日志框架。這樣在使用的時候,我們都是統一使用slf4j的接口,如果我們需要替換日志框架,那么只需要切換依賴,以及加上對應日志框架的配置日志就行。而之所以切換如此絲滑,就在于slf4j內部實現了日志框架實現的自動發現,即上圖標紅位置。
它的自動發現也很簡單,只是去查找org/slf4j/impl/StaticLoggerBinder.class這個類,這個就是slf4j和具體實現框架的一個約定。如果我們想自己實現一個基于slf4j的日志框架實現,那么首先我們就得提供這么一個靜態日志綁定類。
上面只是發現靜態日志綁定類,如果有多個(可能同時引入了多個slf4的日志實現框架),那么會輸出錯誤日志到控制臺。并沒有實際發生任何綁定動作。
實際的綁定動作是執行StaticLoggerBinder.getSingleton();
這里哪個日志框架的StaticLoggerBinder類被調用,就實際用哪個日志框架實現。
(二)日志框架初始化
上面已經講了slf4j如何選擇日志框架,最終取決于StaticLoggerBinder是哪個日志框架,這也是logback 初始化的入。接下來講講logback實際的初始化。
StaticLoggerBinder將綁定ILoggerFactory,使用單例模式,通過StaticLoggerBinder.getSingleton().getLoggerFactory()獲取ILoggerFactory對象。它的初始化是在靜態代碼塊中調用單例的初始化方法:SINGLETON.init();
它初始化了一個ContextInitializer,并傳入StaticLoggerBinder中的默認LoggerContext,所有的初始化配置都是LoggerContext管理,實際上getLoggerFactory也是返回的此對象,所以它實際也是logger的工廠類。之后調用autoConfig,進行配置。我們重點看一下autoConfig:
(1)logback的3種配置方式
從上述代碼可以看到3種配置方式的選擇順序:一個是通過獲取配置文件,如果沒有配置文件,那么就嘗試加載SPI方式配置的Configurator實現類。如果也沒有,那么會使用默認BasicConfigurator。三種配置都有兩個關鍵步驟:
configurator.setContext(loggerContext); configurator.doConfigure(loggerContext);
首先設置日志上下文,因為所有的配置都是圍繞上下文的,所以它是配置器不可或缺的。第二步就是調用doConfigure,執行上下文執行實際的配置。
下面我們從簡單到復雜一一介紹:
a、BasicConfigurator默認配置
默認配置很簡單:
將ConsoleAppender附加到root logger,ConsoleAppender的layout設置為TTLLLayout,它等同于%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"。所以它等同于使用如下配置文件:
<configuration><!-- Appenders --><appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern></encoder></appender><!-- Root Logger --><root><appender-ref ref="CONSOLE"/></root>
</configuration>
日志級別沒有指定,默認是debug級別