掃二維碼與項(xiàng)目經(jīng)理溝通
我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
日志框架分為三大部分,包括日志門面、日志適配器、日志庫(kù)。利用門面設(shè)計(jì)模式,即Facade來進(jìn)行解耦,使日志使用變得更加簡(jiǎn)單,如下圖:

創(chuàng)新互聯(lián)-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價(jià)比鹽都網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫(kù),直接使用。一站式鹽都網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋鹽都地區(qū)。費(fèi)用合理售后完善,10多年實(shí)體公司更值得信賴。
門面設(shè)計(jì)模式是面向?qū)ο笤O(shè)計(jì)模式中的一種,日志框架采用的就是這種模式,類似JDBC的設(shè)計(jì)理念。它只提供一套接口規(guī)范,自身不負(fù)責(zé)日志功能的實(shí)現(xiàn),目的是讓使用者不許奧關(guān)注底層具體是哪個(gè)日志庫(kù)來負(fù)責(zé)日志打印及具體的使用字節(jié)等。目前用得最廣泛的日志門面有 slf4j和commons-logging。
它具體實(shí)現(xiàn)了日志的相關(guān)的功能,主流的日志庫(kù)有三個(gè): log4j、log-jdk、logback。最早java 要想記錄只能通過System.out 或 System.err 來完成,非常不方便。log4j 就是為了解決這一問題而提出的,它是最早誕生的日志庫(kù)。接著JDK也在1.4 版本引入一個(gè)日志庫(kù) java.util.logging.Logger,簡(jiǎn)稱 log-jdk。這樣市面上就出現(xiàn)兩種日志功能的實(shí)現(xiàn),開發(fā)者在使用時(shí)需要關(guān)注所使用的日志庫(kù)的具體字節(jié)。logback是最晚出現(xiàn)的,它與log4j出自同一個(gè)作者,是log4j的升級(jí)版且本身就實(shí)現(xiàn)了 slf4j 的接口。
日志適配器分為兩種場(chǎng)景:
(1) 日志門面適配器,因?yàn)閟lf4j 規(guī)范是后來提出的,在此之前的日志庫(kù)沒有實(shí)現(xiàn) slf4j 的接口的,例如 log4j, 所以,在工程里要想使用slf4j + log4j 的模式,就額外需要一個(gè)適配器(slf4j + log4j2) 來解決接口不兼容的問題。
(2) 日志適配器,在一些老的工程,一開始為了開發(fā)簡(jiǎn)單而直接使用了日志庫(kù)API 來完成日志打印,隨著時(shí)間的推移想將原來直接調(diào)用日志庫(kù)的模型改為業(yè)界標(biāo)準(zhǔn)的門面模式 ( 例如 slf4j +logback 組合) ,但老工程代碼里的打印日志的地方太多,難以改變,所以需要一個(gè)適配器來完成從舊日志庫(kù)的API到slf4j的路由,這樣在不改動(dòng)原有代碼的情況下也能使用slf4j來統(tǒng)一管理日志,而且后續(xù)自由替換具體日志庫(kù)也不成問題。
Commons本身只提供日志接口,具體實(shí)現(xiàn)在運(yùn)行時(shí) 動(dòng)態(tài)尋找對(duì)應(yīng)組件?思路上類似于JDBC的抽象。
JCL動(dòng)態(tài)查找(綁定)日志組件原理如下:
JCL為每一種日志采用了一個(gè)適配器,具體采用哪一個(gè),是動(dòng)態(tài)根據(jù)指定順序查找classpath是否存在相應(yīng)日志的實(shí)現(xiàn),如果JCL運(yùn)行時(shí)沒有找到任何一種第三方的日志實(shí)現(xiàn),則就使用jdk14自帶的java.util.logging(JUL)。
Spring日志就是采JCL,解決了應(yīng)用程序和框架日志不統(tǒng)一的問題,動(dòng)態(tài)去尋找(應(yīng)用程序配置)日志體系的實(shí)現(xiàn)。
默認(rèn)的LogFactory是按照下列的步驟去發(fā)現(xiàn)并決定哪個(gè)日志工具將被使用的,LogFactory按照順序?qū)ふ遥业降谝粋€(gè)工具后中止。
與JCL類似,本身不提供具體實(shí)現(xiàn),只對(duì)外提供接口或者門面,因此它不是具體的日志解決方案,而是通過Facade Pattern 門面模式對(duì)外提供一些 java logging api,這些對(duì)外提供的核心API就是一些接口以及LoggerFactory的工程類。
與Common logging 不同的是其采用在ClassPath下尋找一下jar包來表示具體的采用哪種實(shí)現(xiàn)
SLF4j 靜態(tài)綁定日志組件原理:
JCL方式的common-logging 是動(dòng)態(tài)查找綁定
SLF4j 是靜態(tài)綁定,需要加上橋接包,如 SLF4j-log4j2
可通過如下配置進(jìn)行集成
org.slf4j slf4j-api ${slf4j-api.version} org.slf4j slf4j-log4j12 ${slf4j-log4j12.jar.version} log4j log4j ${log4j.version}
如果是老代碼中直接使用了 log4j 日志庫(kù)提供的接口來打印日志,則還需要引入日志庫(kù)適配器,配置實(shí)例如下所示:
org.slf4j log4j-over-slf4j ${log4j-over-slf4j.version}
如果是新工程,則推薦使用slf4j+logback 模式,因?yàn)閘ogback 自身實(shí)現(xiàn)了 slf4j的接口,無須額外引入適配器,另外,logback 是 log4j 的升級(jí)版,具備比log4j更多的優(yōu)點(diǎn),可通過如下配置進(jìn)行集成:
org.slf4j slf4j-api ${slf4j.version} ch.qos.logback logback-core ${logback.version} ch.qos.logback logback-classic ${logback.version}
我們應(yīng)用使用的是log4j2打印日志;而Spring采用的JCL中不包含log4j2,運(yùn)行時(shí),JCL從ClassPath下尋找日志的實(shí)現(xiàn),如果沒有引用其他實(shí)現(xiàn),最終會(huì)使用JUL實(shí)現(xiàn)。如下圖:
這時(shí)候會(huì)出現(xiàn)什么問題呢?
Spring打印日志和應(yīng)用程序的打印日志不統(tǒng)一,錯(cuò)誤排除還比較困難,而且應(yīng)用程序和Spring框架,日志不統(tǒng)一,太亂了。
為了讓Spring和我們的應(yīng)用程序,采用統(tǒng)一的log4j2日志體系,需要加入適配器,改善上面應(yīng)用程序和框架日志的統(tǒng)一問題(加入適配器后),如下圖:
org.slf4j slf4j-api 1.7.25 org.apache.logging.log4j log4j-slf4j-impl 2.3 org.slf4j jcl-over-slf4j 1.7.13 org.apache.logging.log4j log4j-core 2.3 org.apache.logging.log4j log4j-api 2.3 com.lmax disruptor 3.3.4
SLF4j集成其他日志框架的方法:
在使用SLF4J使用時(shí),需要注意以下事項(xiàng):
- private static final Logger LOGGER = LoggerFactory.getLogger(XXX.class);
logger被定義為static 變量,是因?yàn)檫@個(gè)LOGGER與當(dāng)前類綁定,避免每次都new一個(gè)新對(duì)象,造成資源浪費(fèi)。

我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流