<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          超贊!20年以來Java日志Log4j2發(fā)展史!

          共 4315字,需瀏覽 9分鐘

           ·

          2021-12-17 08:47

          你知道的越多,不知道的就越多,業(yè)余的像一棵小草!

          你來,我們一起精進!你不來,我和你的競爭對手一起精進!

          編輯:業(yè)余草

          segmentfault.com/u/imango

          推薦:https://www.xttblog.com/?p=5300

          這兩天Log4j經(jīng)常霸占頭條,繼前兩天的漏洞修復(fù)和浮現(xiàn)的文章后,今天我們再來聊一聊 Log4j 的發(fā)展史!

          前言

          最早開始擼碼當時就遇到幾次日志jar包沖突的問題,當時也是很煩躁,畢竟了解的也不多,什么那里4j,這里4j,還有什么橋接包,而且在我感覺他們的包名都還差不多??!我當時是比較懵逼的,上網(wǎng)搜了下,隨便看到一個類似這種橋接過去橋接過來的圖我就懵,都是些啥玩意兒。

          Log4j橋接

          最近項目中突然發(fā)現(xiàn)我們自己的工程對于日志的記錄也不是很好,很多各種日志的注解大家用的也不一樣,有@Log4j,也有@Slf4j的,也有@Log4j2的,索性干脆徹底去了解一下日志系統(tǒng)。

          由于個人一直覺得現(xiàn)在學(xué)習(xí)技術(shù)是很好的年代,畢竟我們在前人已經(jīng)踩過的坑,總結(jié)過的經(jīng)驗之上來學(xué)習(xí),相當于站在了巨人的肩膀上,但同時也是最壞的時代,我們對于新技術(shù)可能還是很了解,但是這些新技術(shù)到底為什么出現(xiàn),它們到底解決了什么問題,時代選擇了這些技術(shù)一定是有原因的,我們不清楚技術(shù)發(fā)展的歷史,就像國外不清楚我們中華民族的歷史,所以會曲解我們一樣。

          言歸正傳,雖然看著日志系統(tǒng)很亂,很難梳理清楚,可能名字都不是很好記,但我們要是從日志系統(tǒng)本身的發(fā)展歷史去了解一次,可能就會更加明白為什么會出現(xiàn)現(xiàn)在這種情況了。

          發(fā)展歷史

          System.out和System.err

          這應(yīng)該是最早的日志記錄方式吧,但是不靈活也不可配置,要么就是全部打印,要么就是全部不打印,沒有一個統(tǒng)一的日志級別。另外性能也不高,還讓程序變成串行化,具體可以參考:都 9102 了,你還不知道 System.out.println 的危害!

          Log4j

          在1996年初,E.U.SEMPER(歐洲安全電子市場)項目決定編寫自己的跟蹤API,最后該API演變?yōu)?code style="margin-right: 2px;margin-left: 2px;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(53, 148, 247);background: rgba(59, 170, 250, 0.1);padding-right: 2px;padding-left: 2px;border-radius: 2px;height: 21px;line-height: 22px;">Log4j,Log4j日志軟件包一經(jīng)推出就備受歡迎,當然這里必須要提到一個人,就是Log4j的主要貢獻者,這個大佬:Ceki Gülcü

          Ceki Gülcü

          可能應(yīng)該叫巨佬了。。。后面你就明白了,后來Log4j成為了Apache基金會項目中的一員,同時Log4j的火爆,讓Log4j一度成為業(yè)內(nèi)日志標桿。(據(jù)說Apache基金會還曾經(jīng)建議Sun引入Log4jjava的標準庫中,但是sun拒絕了)。

          JUL(Java Util Logging)

          果然Sun有自己的考慮,2002年2月Java1.4發(fā)布,Sun竟然推出了自己的日志庫Java Util Logging,其實很多日志的實現(xiàn)思想也都是仿照Log4j,畢竟Log4j先出來很多年了,已經(jīng)很成熟了此時,這兩個日志工具打架,顯然Log4j是更勝一籌。

          它們打架感覺就是互相競爭,Sun心里可能在想,不就是做個日志工具嘛,誰不會!當然好景不長。

          JCL(Jakarta Commons Logging)

          Apache: 玩編程,誰玩的過我!你不讓我成為JDK標準,我就自己成為日志標準,哼?。ㄍ耆珎€人意淫。。。)

          于是JUL剛出來不久,2002年8月Apache又推出了日志接口Jakarta Commons Logging,也就是日志抽象層,當然也提供了一個默認實現(xiàn)Simple Log,這野心很大,想一統(tǒng)日志抽象(就像以前的JDBC一統(tǒng)數(shù)據(jù)庫訪問層),讓日志產(chǎn)品去實現(xiàn)它的抽象,這樣只要你的日志代碼依賴的是JCL的接口,你就可以很方便的在Log4jJUL之間做切換,當時日志領(lǐng)域大概是這樣的結(jié)構(gòu),當然也還是方便理解的,也很優(yōu)雅。

          Jakarta Commons Logging

          但是好景不長,在使用過程中,雖然現(xiàn)在日志系統(tǒng)在JCL的統(tǒng)一下很優(yōu)雅,很美好,但大家發(fā)現(xiàn)了JCL還不夠好,有些人甚至認為JCL造成的問題比解決的問題還多...emmm

          ?

          http://tapestryjava.blogspot.com/2007/08/so-long-commons-logging-hello-slf4j.html

          ?
          JUL日志框架

          Slf4j(Simple Logging Facade for Java)

          所以大佬粗線,「Ceki Gülcü」(也就是Log4j的作者)由于一些原因離開了Apache,之后覺得JCL不好,于是于2005年自己擼出一個新工程,也就是一套新日志接口(有得也叫日志門面):Slf4j(Simple Logging Facade for Java),感覺粗來了么。。。這戰(zhàn)爭的硝煙,明顯這個Slf4j是直指JCL啊,但是后面確實也證明了Slf4j是要比JCL在很多地方更優(yōu)秀。

          「Ceki Gülcü」:玩接口,我一個人就是一支軍隊!

          但是由于Slf4j出來的較晚,而且還只是一個日志接口,所以之前已經(jīng)出現(xiàn)的日志產(chǎn)品,如JULLog4j都是沒有實現(xiàn)這個接口的,所以尷尬的是光有一個接口,沒有實現(xiàn)的產(chǎn)品也是很憋屈啊,就算開發(fā)者想用Slf4j也是用不了,這時候,大佬發(fā)話了。

          「Ceki Gülcü」:別急,我早幫你們想好了,要讓Sun或者Apache這兩個龐然大物來實現(xiàn)我的接口,太南啦,老鐵,但。。。我?guī)湍銈儗崿F(xiàn),不就完了么。。。

          于是大佬「Ceki Gülcü」擼出了之前提到的橋接包,也就是這種類似適配器模式。

          適配器模式

          好了,大佬提供了橋接包,于是日志系統(tǒng)現(xiàn)在有了這樣的結(jié)構(gòu)。

          日志系統(tǒng)結(jié)構(gòu)

          但是其實之前很多Java應(yīng)用應(yīng)該依賴的JCL,所以光有日志產(chǎn)品橋接包,好像還不夠
          「Ceki Gülcü」:沒問題,不就是不夠橋接包么,我寫,我來證明Slf4j是最完美的
          于是有了JCL的橋接包。

          JCL的橋接包

          相當于此時的橋接包就是分了兩種場景

          1. 之前Java應(yīng)用用的日志接口(如JCL
          2. 之前Java應(yīng)用用的日志產(chǎn)品(如Log4j

          那好,那我們?nèi)绻倏紤]一下這種場景呢?

          假設(shè)哈,你的Java應(yīng)用使用了Spring的第三方的框架,但是假設(shè)Spring默認用JCL,并且最終用的JUL打印的日志,但是你的系統(tǒng)使用了Slf4j作為日志接口,日志產(chǎn)品使用了Log4j,那。。。不出意外的話。。。你將有兩種日志輸出,兩種日志的打印方式不統(tǒng)一,到時候解決bug的時候就很惱火,而且配置日志的配置文件還需要兩份。

          配置日志

          所以為了方便統(tǒng)一應(yīng)用中的所有日志,大佬發(fā)話了。

          「Ceki Gülcü」:沒事,大家都選擇用Slf4j統(tǒng)一吧,我來幫大家統(tǒng)一,沒有事是橋接包解決不了的,有的話,那就再來個。

          Slf4j橋接包

          當然此時這種場景也是符合之前說的兩種情況的,因此現(xiàn)在日志系統(tǒng)大體應(yīng)該是這樣的。

          日志系統(tǒng)

          總結(jié)一句話就是:大佬擼完。。。

          但好景又不長,大佬畢竟是大佬,Log4j不就是自己寫的么,所以最清楚Log4j缺點的人也正是他。

          Logback

          由于使用Slf4j,需要一次橋接包,也就是之前的日志產(chǎn)品都不是正統(tǒng)的Slf4j的實現(xiàn),因此,2006年,出自「Ceki Gülcü」之手的日志產(chǎn)品Logback應(yīng)運而生,而且大佬還專門寫了一篇:

          ?

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

          ?
          Logback

          是不是這太針對了。。。哈哈哈哈,就是這么無情,當然都是他寫的,他肯定是最清楚這兩者實現(xiàn)的區(qū)別。

          肯定的,Logback是完美實現(xiàn)了Slf4j,于是現(xiàn)在日志系統(tǒng)變成了。

          Logback實現(xiàn)了Slf4j

          ok了,現(xiàn)在咱們有了2個日志接口,3個日志產(chǎn)品,大家也都看起來相安無事。。。但。。。Slf4j+Logback的模式,顯然很沖擊JCL+Log4j,并且本身Logback確實比Log4j性能更優(yōu),設(shè)計更為合理,所以。。。老東家Apache可就坐不住了。

          Log4j2

          在2012年,Apache直接推出新項目,不是Log4j1.x升級,而是新項目Log4j2,因為Log4j2是完全不兼容Log4j1.x的。

          并且很微妙的,Log4j2幾乎涵蓋Logback所有的特性(這不是對著干是啥~而且還有抄襲的嫌疑。。。哈哈哈),更甚者的Log4j2也搞了分離的設(shè)計,分化成log4j-apilog4j-core,這個log4j-api也是日志接口,log4j-core才是日志產(chǎn)品。。。

          emmm,我看到這,我都有點崩潰了。

          現(xiàn)在我們可有了3個日志接口,以及4個日志產(chǎn)品。。。當然Apache也知道該做啥,為了讓大家可以接入自己的Log4j2,那不就是橋嘛,不就是橋嘛,Apache也麻溜的推出了它的橋接包,所以。。。

          唉,所以我都不敢畫圖了。。。

          前方高能?。?!

          前方高能?。?!

          前方高能!?。?/span>

          Java日志框架

          總結(jié)到這,我們可以吸取什么經(jīng)驗么?

          1. 不寫接口的壞處
          2. 沒有什么問題是加一個層適配器(接口)解決不了的,如果有,那就再加一層

          最佳實踐

          了解了日志的發(fā)展歷史,那現(xiàn)在我們再回過頭來看看如果,你的系統(tǒng)在選擇日志方案的時候,如何抉擇呢?畢竟我們3個日志接口,以及4個日志產(chǎn)品。

          • 顯然第一點是使用日志接口的API而不是直接使用日志產(chǎn)品的API

            這一條也是必須的,也是符合依賴倒置原則的,我們應(yīng)該依賴日志的抽象,而不是日志的實現(xiàn)

          • 日志產(chǎn)品的依賴只添加一個

            當然也這個也是必須的,依賴多個日志產(chǎn)品,只會讓自己的應(yīng)用處理日志顯得更復(fù)雜,不可統(tǒng)一控制

          • 把日志產(chǎn)品的依賴設(shè)置為Optionalruntime scope

            其中Optional是為了依賴不會被傳遞,比如別的人引用你這個jar,就會被迫使用不想用的日志依賴

          ??<dependency>
          ??????<groupId>org.apache.logging.log4jgroupId>
          ??????<artifactId>log4j-coreartifactId>
          ??????<version>${log4j.version}version>
          ??????<optional>trueoptional>
          ??dependency>

          scope設(shè)置為runtime,是可以保證日志的產(chǎn)品的依賴只有在運行時需要,編譯時不需要,這樣,開發(fā)人員就不會在編寫代碼的過程中使用到日志產(chǎn)品的API

          <dependency>
          ????<groupId>org.apache.logging.log4jgroupId>
          ????<artifactId>log4j-slf4j-implartifactId>
          ????<version>${log4j.version}version>
          ????<scope>runtimescope>
          dependency>

          謝謝觀看o( ̄▽ ̄)d

          最后留一個懸念,我們的大佬「Ceki Gülcü」為啥離開apache?

          瀏覽 142
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  4438全国最大成人网 | 台湾精品一区二区 | 久草手机在线视频 | 男人的天堂黄片 | 亚洲性色网 |