alancxx

          ------簡(jiǎn)單就是美

          java日志組件分析

           如果對(duì)于commons-loging log4j slf4j LogBack 等都已經(jīng)非常清楚了,可以忽略本文。幾次解決日志沖突問題時(shí)對(duì)這幾個(gè)概念的簡(jiǎn)單總結(jié),希望對(duì)這塊基礎(chǔ)沒有理解透的同學(xué)能有所幫助,當(dāng)然如果對(duì)這塊有更深刻理解的同學(xué),也貢獻(xiàn)出自己的知識(shí)和見解。

          一、     概念

          Commons-logging : apache最早提供的日志的門面接口。避免和具體的日志方案直接耦合。類似于JDBC api 接口,具體的的JDBC driver 實(shí)現(xiàn)由各數(shù)據(jù)庫提供商實(shí)現(xiàn)。通過統(tǒng)一接口解耦,不過其內(nèi)部也實(shí)現(xiàn)了一些簡(jiǎn)單日志方案。

          Log4j : 經(jīng)典的一種日志解決方案。內(nèi)部把日志系統(tǒng)抽象封裝成Logger appender pattern 等實(shí)現(xiàn)。我們可以通過配置文件輕松的實(shí)現(xiàn)日志系統(tǒng)的管理和多樣化配置。

          Slf4j : 全稱為Simple Logging Facade for JAVAjava簡(jiǎn)單日志門面。是對(duì)不同日志框架提供的一個(gè)門面封裝。可以在部署的時(shí)候不修改任何配置即可接入一種日志實(shí)現(xiàn)方案。和commons-loging 應(yīng)該有一樣的初衷。個(gè)人感覺設(shè)從計(jì)上更好一些,沒有commons 那么多潛規(guī)則。同時(shí)有兩個(gè)額外特點(diǎn):

          1. 能支持多個(gè)參數(shù),并通過{} 占位符進(jìn)行替換,避免老寫logger.isXXXEnabled 這種無奈的判斷,帶來性能提升見:http://www.slf4j.org/faq.html#logging_performance

          2.OSGI 機(jī)制更好兼容支持

          一圖勝千言,官網(wǎng)上的一個(gè)圖:

           

          從上圖可以發(fā)現(xiàn),選擇還是很多的。

          Logback : LOGBack 作為一個(gè)通用可靠、快速靈活的日志框架,將作為L(zhǎng)og4j 的替代和SLF4J 組成新的日志系統(tǒng)的完整實(shí)現(xiàn)。官網(wǎng)上稱具有極佳的性能,在關(guān)鍵路徑上執(zhí)行速度是log4j 的10 倍,且內(nèi)存消耗更少。具體優(yōu)勢(shì)見:

          http://logback.qos.ch/reasonsToSwitch.html

          二、     常見日志方案和注意事項(xiàng)

          1.Commons-logging+log4j : 經(jīng)典的一個(gè)日志實(shí)現(xiàn)方案。出現(xiàn)在各種框架里。如spring 、webx 、ibatis 等等。直接使用log4j 即可滿足我們的日志方案。但是一般為了避免直接依賴具體的日志實(shí)現(xiàn),一般都是結(jié)合commons-logging 來實(shí)現(xiàn)。常見代碼如下:

          import org.apache.commons.logging.Log;

          import org.apache.commons.logging.LogFactory;

          private static Log logger = LogFactory.getLog(CommonsLoggingTest.class);

          代碼上,沒有依賴任何的log4j 內(nèi)部的類。那么log4j 是如何被裝載的?

          Log 是一個(gè)接口聲明。LogFactory 的內(nèi)部會(huì)去裝載具體的日志系統(tǒng),并獲得實(shí)現(xiàn)該Log 接口的實(shí)現(xiàn)類。而內(nèi)部有一個(gè)Log4JLogger 實(shí)現(xiàn)類對(duì)Log 接口同時(shí)內(nèi)部提供了對(duì)log4j logger 的代理。LogFactory 內(nèi)部裝載日志系統(tǒng)流程:

          1.   首先,尋找org.apache.commons.logging.LogFactory 屬性配置

          2.   否則,利用JDK1.3 開始提供的service 發(fā)現(xiàn)機(jī)制,會(huì)掃描classpah 下的META-INF/services/org.apache.commons.logging.LogFactory 文件,若找到則裝載里面的配置,使用里面的配置。

          3.   否則,從Classpath 里尋找commons-logging.properties ,找到則根據(jù)里面的配置加載。

          4.   否則,使用默認(rèn)的配置:如果能找到Log4j 則默認(rèn)使用log4j 實(shí)現(xiàn),如果沒有則使用JDK14Logger 實(shí)現(xiàn),再?zèng)]有則使用commons-logging 內(nèi)部提供的SimpleLog 實(shí)現(xiàn)。

          從上述加載流程來看,如果沒有做任何配置,只要引入了log4j 并在classpath 配置了log4j.xml ,則commons-logging 就會(huì)使log4j 使用正常,而代碼里不需要依賴任何log4j 的代碼。

          2.Commons-logging+log4j+slf4j

          如果在原有commons-logging 系統(tǒng)里,如果要遷移到slf4j, 使用slf4j 替換commons-logging ,也是可以做到的。原理使用到了上述commons-logging 加載的第二點(diǎn)。需要引入Org.slf4j.jcl-over-slf4j-1.5.6.jar 。這個(gè)jar 包提供了一個(gè)橋接,讓底層實(shí)現(xiàn)是基于slf4j 。原理是在該jar 包里存放了配置META-INF/services/org.apache.commons.logging.LogFactory =org.apache.commons.logging.impl.SLF4JLogFactory ,而commons-logging 在初始化的時(shí)候會(huì)找到這個(gè)serviceId ,并把它作為L(zhǎng)ogFactory 。

          完成橋接后,那么那么簡(jiǎn)單日志門面SLF4J 內(nèi)部又是如何來裝載合適的log 呢?

          原理是SLF4J 會(huì)在編譯時(shí)會(huì)綁定import org.slf4j.impl.StaticLoggerBinder; 該類里面實(shí)現(xiàn)對(duì)具體日志方案的綁定接入。任何一種基于slf4j 的實(shí)現(xiàn)都要有一個(gè)這個(gè)類。如:

          org.slf4j.slf4j-log4j12-1.5.6: 提供對(duì) log4j 的一種適配實(shí)現(xiàn)。

          Org.slf4j.slf4j-simple-1.5.6: 是一種 simple 實(shí)現(xiàn),會(huì)將 log 直接打到控制臺(tái)。

          ……

          那么這個(gè)地方就要注意了:如果有任意兩個(gè)實(shí)現(xiàn)slf4j 的包同時(shí)出現(xiàn),那就有可能釀就悲劇,你可能會(huì)發(fā)現(xiàn)日志不見了、或都打到控制臺(tái)了。原因是這兩個(gè)jar 包里都有各自的org.slf4j.impl.StaticLoggerBinder ,編譯時(shí)候綁定的是哪個(gè)是不確定的。這個(gè)地方要特別注意!!出現(xiàn)過幾次因?yàn)檫@個(gè)導(dǎo)致日志錯(cuò)亂的問題。

          3.Slf4j+logback

          Slf4j 和log4j 作者都是同一個(gè)人。

          Logback 號(hào)稱在性能各方面有很多優(yōu)勢(shì),也很誘人。

          直接使用SLf4j 也很簡(jiǎn)單:

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

          public class HelloWorld {
            public static void main(String[] args) {
              Logger logger = LoggerFactory.getLogger(HelloWorld.class);
              logger.info("Hello World");
            }
          }

          代碼里也看不到任何具體日志實(shí)現(xiàn)方案的痕跡。

          Logback 沒用過,看到過一些誘人介紹。具體大家可以去研究。logback 。

          注意事項(xiàng)

          使用日志配置的時(shí)候一定要明白需求,同時(shí)避免沖突。

          如使用SLF4j 的時(shí)候?yàn)榱吮苊鉀_突,一定要保障只有一種實(shí)現(xiàn)類jar 包在里面。

          當(dāng)遇到日志錯(cuò)亂等問題時(shí),可以從這幾個(gè)方面來排查

          posted on 2011-03-04 18:09 蜂鳥 閱讀(714) 評(píng)論(0)  編輯  收藏 所屬分類: j2ee架構(gòu)

          公告

           掌握了XML就掌握了未來!

          導(dǎo)航

          <2025年6月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          統(tǒng)計(jì)

          常用鏈接

          留言簿

          隨筆檔案(1)

          文章分類(17)

          文章檔案(17)

          搜索

          最新評(píng)論

          主站蜘蛛池模板: 阿合奇县| 玛曲县| 万州区| 子洲县| 都匀市| 邓州市| 察雅县| 晋中市| 仙居县| 平利县| 陇西县| 油尖旺区| 缙云县| 高唐县| 微山县| 德安县| 乌拉特中旗| 通州区| 宝鸡市| 巫溪县| 泰兴市| 西贡区| 上蔡县| 巴彦淖尔市| 海阳市| 武威市| 团风县| 秦皇岛市| 平乐县| 垣曲县| 通山县| 定边县| 原平市| 舞阳县| 新和县| 兴隆县| 淳安县| 洪雅县| 始兴县| 儋州市| 钦州市|