java日志框架的前世今生

一摇零、聊聊java中混亂的日志體系

???♀?波妞:先提個(gè)問(wèn)題推掸,你知道哪些日志框架?
???♀?波妞:呃遂黍。终佛。。我說(shuō)說(shuō)搜我聽(tīng)過(guò)的吧雾家,比如log4j铃彰、jul、jcl芯咧、slf4j牙捉、log4j2竹揍、simple log、logback邪铲,已經(jīng)有7個(gè)了芬位,但是肯定不止7個(gè)。
???♂?宗介:臥槽带到,那在項(xiàng)目中我到底該用哪個(gè)昧碉,看得我腦殼痛,它們有啥子關(guān)系沒(méi)得嘛揽惹?
???♀?波妞:別著急被饿,下面讓我慢慢說(shuō)。

二搪搏、先打印幾個(gè)日志看看

1. 使用log4j輸出一下日志
  • 先導(dǎo)入log4j的依賴(lài)
    <dependencies>
      <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
      </dependency>
    </dependencies>
    
  • 然后在classpath下加上log4j的配置文件log4j.properties狭握,日志級(jí)別設(shè)置的是info
    log4j.rootLogger=info,stdout
    # 輸出到控制臺(tái)
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.target=System.out
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %p [%t] %C.%M(%L) | %m%n
    
  • 主程序
    import org.apache.log4j.Logger;
    
    public class Log4j {
        public static void main(String[] args) {
            Logger logger = Logger.getLogger("lof4j");
            logger.info("log4j");
        }
    }
    
  • 運(yùn)行程序,看到控制臺(tái)輸出了日志


    log4j控制臺(tái)輸出效果疯溺,嗯论颅,是白色
2. 使用jul(java.util.logging)輸出一下日志
  • 因?yàn)?code>jul是jdk自帶的日志包,所以不需要添加依賴(lài)囱嫩,直接干恃疯,主程序如下,注意導(dǎo)包導(dǎo)的是java.util.logging.Logger
    import java.util.logging.Logger;
    
    public class Jul {
        public static void main(String[] args) {
            Logger logger = Logger.getLogger("jul");
            logger.info("jul");
        }
    }
    
  • 運(yùn)行程序墨闲,查看控制臺(tái)


    jul控制臺(tái)輸出效果澡谭,發(fā)現(xiàn)它時(shí)紅色滴
3.使用jcl輸出一下日志
  • 先導(dǎo)入jcl的依賴(lài)
    <dependencies>
      <dependency>
          <groupId>commons-logging</groupId>
          <artifactId>commons-logging</artifactId>
          <version>1.2</version>
      </dependency>
    </dependencies>
    
  • 上主程序,這次不是直接通過(guò)new得到一個(gè)logger了损俭,而是使用工廠去拿一個(gè)logger蛙奖,這也是有原因的哈
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    
    public class Jcl {
        public static void main(String[] args) {
            Log log = LogFactory.getLog("jcl");
            log.info("jcl");
        }
    }
    
  • 運(yùn)行看控制臺(tái)


    咦率碾,紅色楼雹?怎么和jul的效果那么像

    deug發(fā)現(xiàn)的確是jul logger
  • log4j的依賴(lài)加上試試愈捅,加上后的依賴(lài)變成了下面的樣子

    <dependencies>
      <dependency>
          <groupId>commons-logging</groupId>
          <artifactId>commons-logging</artifactId>
          <version>1.2</version>
      </dependency>
    
      <dependency>
          <groupId>log4j</groupId>
          <artifactId>log4j</artifactId>
          <version>1.2.17</version>
      </dependency>
    </dependencies>  
    
  • 再次運(yùn)行脆贵,看看控制臺(tái)是什么樣子


    季眷?首繁?夯膀?白色旧找?怎么又變的和log4j的效果一樣了日裙,小朋友有很多問(wèn)號(hào)啊

    打個(gè)斷點(diǎn)進(jìn)一步驗(yàn)證吹艇,發(fā)現(xiàn)的確是log4j logger
  • 聰明的你可能已經(jīng)猜到了,jcl根本不是一個(gè)日志實(shí)現(xiàn)(或者說(shuō)日志產(chǎn)品)昂拂,而是一個(gè)日志抽象層受神,主程序里面那個(gè)LogFactory.getLog("jcl")拿到是才一個(gè)具體的日志產(chǎn)品的對(duì)象。所以我們猜測(cè)jcl的結(jié)構(gòu)是下面這樣的

  • 為了進(jìn)一步證實(shí)我們的猜想格侯,我們看看源碼鼻听,在LogFactoryImpl這個(gè)類(lèi)中發(fā)現(xiàn)一段關(guān)鍵代碼

    • 定義了一個(gè)成員變量classesToDiscover
      private static final String[] classesToDiscover = {
              LOGGING_IMPL_LOG4J_LOGGER,  // org.apache.commons.logging.impl.Log4JLogger
              "org.apache.commons.logging.impl.Jdk14Logger",
              "org.apache.commons.logging.impl.Jdk13LumberjackLogger",
              "org.apache.commons.logging.impl.SimpleLog"
      };
      
    • 代碼片段
      for(int i=0; i<classesToDiscover.length && result == null; ++i) {
          result = createLogFromClass(classesToDiscover[i], logCategory, true);
      }
      
      if (result == null) {
          throw new LogConfigurationException("No suitable Log implementation");
      }
      return result;
      
    • 所以玄機(jī)就在這里财著,LogFactoryImpl中先定義了一個(gè)成員變量classesToDiscover,它是一個(gè)String數(shù)組撑碴,里面包含了log4jjullogger的全限定名撑教。然后會(huì)在代碼里面遍歷這個(gè)數(shù)組,每次拿到一個(gè)全限定名并調(diào)用createLogFromClass嘗試去實(shí)例化對(duì)象醉拓,如果沒(méi)實(shí)例化成功則會(huì)返回null伟姐,繼續(xù)使用下一個(gè)全類(lèi)名去實(shí)例化對(duì)象∫诼保可以看到數(shù)組的第二個(gè)元素是Jdk14Logger玫镐,它封裝的是jul里面的logger,而juljdk自帶的庫(kù)怠噪,所以99.99%的情況下,如果你沒(méi)導(dǎo)入log4jjar包杜跷,最終返回的loggerjullogger傍念。如果導(dǎo)入了log4jjar包,那么在遍歷數(shù)組第一個(gè)元素后就會(huì)得到logger對(duì)象了葛闷,此時(shí)得到的就是log4jlogger對(duì)象憋槐。這就是前面的例子中為什么沒(méi)加log4j依賴(lài)時(shí),使用的jullogger淑趾,加了log4j依賴(lài)后使用的是log4jlogger原因阳仔。最后需要注意juljava.util.logging包的簡(jiǎn)稱(chēng),是jdk4正式發(fā)布的日志庫(kù)扣泊,可以說(shuō)是老妖怪近范。而Jdk13LumberjackLogger應(yīng)該是對(duì)jdk1.3及以前版本的東西的封裝(沒(méi)有深究過(guò),)延蟹,可以說(shuō)是個(gè)超級(jí)老妖怪评矩。你肯定不會(huì)去用jdk3去做開(kāi)發(fā),所以不用在意Jdk13LumberjackLogger阱飘。至于SimpleLog斥杜,這個(gè)是jcl的默認(rèn)實(shí)現(xiàn),簡(jiǎn)單但是功能不夠強(qiáng)大沥匈,很少用蔗喂,所以也不用在意啦。
4. 小總結(jié)

通過(guò)上面的demo高帖,我們發(fā)現(xiàn)jcl是一個(gè)日志抽象層缰儿。我們面向抽象編程,可以讓我們的程序可擴(kuò)展散址,可以無(wú)縫切換日志產(chǎn)品返弹,比如你今天用的log4j锈玉,明天想用jul了,那么直接把項(xiàng)目中的log4j依賴(lài)排除掉即可义起。但是有個(gè)問(wèn)題拉背,看了源碼發(fā)現(xiàn)jcl只支持4個(gè)日志產(chǎn)品,還有兩個(gè)是沒(méi)用的默终,也就說(shuō)jcl只支持log4jjul∫喂祝現(xiàn)在市面上這么多日志產(chǎn)品,還有什么logback呀齐蔽、nop呀什么的两疚。我如果要用loback,想面向抽象編程jcl也不支持呀含滴。的確是的诱渤,因?yàn)?code>jcl已經(jīng)很久沒(méi)有更新了,沒(méi)有對(duì)新的日志框架做適配谈况。但是好消息是有個(gè)后起之秀來(lái)代替它勺美,它就是slf4j

三碑韵、下面我們開(kāi)始來(lái)說(shuō)說(shuō)java中日志系統(tǒng)的前世今生吧

起源:System.out和System.err

這應(yīng)該是最早的記錄日志的方式赡茸,不靈活、不能根據(jù)實(shí)際需要進(jìn)行一些選項(xiàng)配置

Ⅰ祝闻、1996年占卧,Log4j橫空出世

1996年初,E.U.SEMPER(歐洲安全電子市場(chǎng))項(xiàng)目決定編寫(xiě)自己的跟蹤API联喘,最后該API演變?yōu)?code>Log4j华蜒,Log4j日志軟件包一經(jīng)推出就備受歡迎,當(dāng)然這里必須要提到一個(gè)人豁遭,他是Log4j的主要貢獻(xiàn)者友多,這個(gè)大佬叫??Ceki Gülcü,可能應(yīng)該叫巨佬堤框。域滥。。后面你就明白了蜈抓。后來(lái)Log4j成為了Apache基金會(huì)項(xiàng)目中的一員启绰,同時(shí)Log4j的火爆,讓Log4j一度成為業(yè)內(nèi)日志標(biāo)桿沟使。(據(jù)說(shuō)???♂?Apache基金會(huì)還曾經(jīng)建議????♀?Sun引入Log4jjava的標(biāo)準(zhǔn)庫(kù)中委可,但是????♀?sun拒絕了,????♀?sun可能是有自己的私心)。

Ⅱ着倾、2002年2月拾酝,JUL誕生

果然????♀?sun是有私心的(??我自己的親兒子怎么能用你擼出來(lái)的東西),于是在20022Java1.4發(fā)布卡者,????♀?sun正式推出了自己的日志庫(kù)Java Util Logging蒿囤,其實(shí)很多日志的實(shí)現(xiàn)思想也都是仿照Log4j,畢竟Log4j先出來(lái)很多年了崇决,已經(jīng)很成熟了此時(shí)材诽,這兩個(gè)日志工具打架,顯然Log4j是更勝一籌恒傻。它們打架其實(shí)就是互相競(jìng)爭(zhēng)脸侥,????♀?sun心里可能在想,不就是做個(gè)日志工具嘛盈厘,誰(shuí)不會(huì)睁枕!當(dāng)然好景不長(zhǎng)。

Ⅲ沸手、2002年8月外遇,JCL(Jakarta Commons Logging)出生,想一統(tǒng)江湖

終于罐氨,???♂?Apache發(fā)言了, 玩編程滩援,誰(shuí)玩的過(guò)我栅隐!你不讓我成為jdk標(biāo)準(zhǔn),我就把自己變成日志的標(biāo)準(zhǔn)玩徊,哼??W馇摹!6鞲ぁ泣棋!于是JUL剛出來(lái)不久,20028月???♂?Apache又推出了日志接口Jakarta Commons Logging畔塔,也就是日志抽象層潭辈,當(dāng)然也提供了一個(gè)默認(rèn)實(shí)現(xiàn)Simple Log,這野心很大澈吨,想一統(tǒng)日志抽象(就像以前的JDBC一統(tǒng)數(shù)據(jù)庫(kù)訪問(wèn)層)把敢,讓日志產(chǎn)品去實(shí)現(xiàn)它的抽象,這樣只要你的日志代碼依賴(lài)的是JCL的接口谅辣,你就可以很方便的在實(shí)現(xiàn)了jcl接口的日志產(chǎn)品之間做切換修赞,當(dāng)時(shí)日志領(lǐng)域大概是這樣的結(jié)構(gòu),當(dāng)然也還是很容易理解的桑阶,也很優(yōu)雅柏副。

但是好景不長(zhǎng)勾邦,在使用過(guò)程中,雖然現(xiàn)在日志系統(tǒng)在JCL的統(tǒng)一下很優(yōu)雅割择,很美好眷篇,但大家發(fā)現(xiàn)了JCL還不夠好,有些人甚至認(rèn)為JCL造成的問(wèn)題比解決的問(wèn)題還多...??????【抱怨地址】

Ⅳ锨推、2005年铅歼,slf4j(Simple Logging Facade for Java)出世,最后證明换可,后來(lái)者居上

大佬??Ceki Gülcü(也就是Log4j的作者)由于一些原因離開(kāi)了???♂?Apache椎椰,之后覺(jué)得jcl不好,于是于2005年自己擼出一個(gè)新工程沾鳄,也就是一套新日志接口(也叫java簡(jiǎn)單日志門(mén)面):slf4jSimple Logging Facade for Java)慨飘,感覺(jué)粗來(lái)了么。译荞。瓤的。這戰(zhàn)爭(zhēng)的硝煙 ??,明顯這個(gè)Slf4j是劍指jcl啊吞歼,但是后面確實(shí)也證明了slf4j是要比jcl的戰(zhàn)斗力更強(qiáng)圈膏。

??Ceki Gülcü心想,和我玩接口篙骡,我一個(gè)人就是一支軍隊(duì)??稽坤!玩死你們??。

slf4j綁定器:綁定器是什么糯俗?

由于slf4j出生的較晚尿褪,而且還只是一個(gè)日志接口,所以之前已經(jīng)出現(xiàn)的日志產(chǎn)品得湘,如JCLLog4j都是沒(méi)有實(shí)現(xiàn)這個(gè)接口的杖玲,所以尷尬的是光有一個(gè)接口,沒(méi)有實(shí)現(xiàn)的產(chǎn)品也是很憋屈啊淘正,就算開(kāi)發(fā)者想用Slf4j也是用不了摆马,這時(shí)候,巨佬??Ceki Gülcü發(fā)話了鸿吆。

??Ceki Gülcü:咳咳....今膊,別急,我早幫你們想好了伞剑,要讓????♀? sun或者???♂?Apache這兩個(gè)家伙來(lái)實(shí)現(xiàn)我的接口斑唬,太南啦,老鐵,但恕刘。缤谎。。我?guī)湍銈儗?shí)現(xiàn)褐着,不就完了么坷澡。。含蓉。

于是巨佬??Ceki Gülcü擼了個(gè)綁定器(巨佬??Ceki Gülcü的slf4j官網(wǎng)說(shuō)的是slf4j binding频敛,就叫它綁定器吧),他是這樣說(shuō)的馅扣,只需要在你的類(lèi)路徑下替換不同的綁定器斟赚,就可以實(shí)現(xiàn)日志框架的切換。比如要將jul替換成log4j差油,只需要用slf4j-log4j-xxx.jar替換slf4j-jdk14-xxx.jar(xxx表示版本號(hào))拗军。下面三張圖,仔細(xì)品味下哦蓄喇,特別是第二張发侵。

官網(wǎng)截圖
官網(wǎng)給的圖,仔細(xì)看看哦妆偏,不要看到英文就溜刃鳄,我英文也很渣,但是也用有道神器把它看懂了的
對(duì)上圖做個(gè)小總結(jié)钱骂,slf4j的基本結(jié)構(gòu)就是醬紫
slf4j橋接器:橋接器是什么?
巨佬Ceki Gülcü這樣介紹橋接器的

巨佬??Ceki Gülcü的意思就是叔锐,你的組件可能依賴(lài)slf4j以外的日志組件,并且這些日志組件不能改變成slf4j罐柳,這樣就會(huì)產(chǎn)生日志沖突掌腰,在你的應(yīng)用中就會(huì)出現(xiàn)兩種及以上的日志狰住,造成日志混亂张吉。對(duì)于這種場(chǎng)景,巨佬??Ceki Gülcü提供了slf4j橋這個(gè)東西催植,讓其他框架的日志可以重定向到slf4j肮蛹,這樣就完美解決了日志沖突問(wèn)題。

下面舉一個(gè)栗子创南,先喝杯水??:
假設(shè)你的應(yīng)用中使用的日志框架是jul伦忠,而??spring使用的jcljcl又使用的log4j稿辙,如下圖昆码。

日志框架沖突場(chǎng)景

現(xiàn)在有兩種解決方式:

  • 一是使用log4j,因?yàn)槟憧梢愿淖约旱拇a,所以可以直接更換slf4j綁定器赋咽,將應(yīng)用使用的日志框架切換到log4j

    將綁定器從 slf4j-jdk14 換成 slf4j-log4j 就ok了

  • 二是如果不想妥協(xié)旧噪,我就想使用juc,這個(gè)時(shí)候脓匿,你又改不了人家??spring的代碼淘钟,讓??spring不使用log4j,怎么辦陪毡,橋接器登場(chǎng)

    jcl-over-slf4j橋接器中重寫(xiě)了log4j米母,也就是說(shuō)jcl-over-slf4j有一個(gè)山寨版的log4j,這個(gè)log4j會(huì)重定向到slf4j毡琉,最終使用juc铁瞒。

官網(wǎng)給出的slf4j橋接包的結(jié)構(gòu)圖,仔細(xì)品味哦
看了上面的介紹后是不是覺(jué)得绊起,有木有jio得巨佬??Ceki Gülcü真的是個(gè)巨佬了精拟,他一個(gè)人干贏了????♀? sun和???♂?Apache,讓他們做自己的小弟??虱歪。

??Ceki Gülcü心想:??挖鼻屎蜂绎,??和我斗,我一個(gè)人就能爆發(fā)出你們兩個(gè)加起來(lái)乘上99999的力量??笋鄙。

Logback(2006年)

巨佬??Ceki Gülcü覺(jué)得师枣,使用slf4j,要么需要加上綁定器萧落,要么需要家還是那個(gè)橋接包践美,因?yàn)槟切┤罩井a(chǎn)品都不是slf4j的親生兒子,所以他覺(jué)得應(yīng)該讓slf4j有個(gè)親兒子找岖,于是在2006年logback誕生了陨倡,logback完美實(shí)現(xiàn)了slf4j。由于log4j也是自己寫(xiě)的许布,他專(zhuān)門(mén)寫(xiě)了篇文章建議在你的應(yīng)用中首先考慮使用logback而不是log4j兴革,并指出logback相比log4j更好的原因--->文章地址,具體優(yōu)點(diǎn)體現(xiàn)在性能更好蜜唾、更安全可靠杂曲、更節(jié)約內(nèi)存等等,具體可以去看文章袁余,這里不多費(fèi)口舌了擎勘。

先對(duì)上面提到的東西做個(gè)小總結(jié),這里面只畫(huà)出了常用的日志產(chǎn)品颖榜,也就是log4j棚饵、jul和logback
小總結(jié)
Ⅴ煤裙、2012年,戰(zhàn)火還未結(jié)束噪漾,天降log4j2

在2012年积暖,???♂?Apache直接推出新項(xiàng)目,不是對(duì)log4j1.x升級(jí)怪与,而是新項(xiàng)目log4j2夺刑,因?yàn)?code>log4j2是完全不兼容log4j1.x

并且很微妙的,log4j2幾乎涵蓋logback所有的特性(這不是對(duì)著干是啥~而且還有抄襲的嫌疑分别。遍愿。。哈哈哈)耘斩,更甚者的Log4j2也搞了分離的設(shè)計(jì)沼填,分化成log4j-apilog4j-core,這個(gè)log4j-api也是日志接口括授,log4j-core才是日志產(chǎn)品坞笙。。荚虚。

emmm薛夜,我看到這,我都有點(diǎn)崩潰了

現(xiàn)在我們可有了3個(gè)日志接口(jcl版述、slf4j梯澜、log4j2),以及4個(gè)日志產(chǎn)品(log4j渴析、jul晚伙、simple-loglogback)俭茧。咆疗。。當(dāng)然???♂?Apache也知道該做啥母债,為了讓大家可以接入自己的Log4j2午磁,那不就是綁定器嘛,或者要不就是橋接器(在官網(wǎng)只看到了橋接器场斑,沒(méi)有看到綁定器漓踢,我猜應(yīng)該是???♂?Apache太懶了)牵署,???♂?Apache也麻溜的推出了它的橋接包漏隐。

??。奴迅。青责。最后的圖大概是這樣挺据。嗯,畫(huà)完這張圖我掉了99999根頭發(fā)????脖隶。

Ⅵ扁耐、現(xiàn)在是2020年,各個(gè)公司使用不同的日志框架产阱,沒(méi)具體統(tǒng)計(jì)過(guò)婉称,我覺(jué)得是slf4j占主導(dǎo)地位

四、前上面說(shuō)了那么多构蹬,現(xiàn)在說(shuō)一點(diǎn)注意事項(xiàng)和總結(jié)

??先說(shuō)注意事項(xiàng)??:
  • 如果系統(tǒng)系統(tǒng)采用slf4j王暗,那么需要導(dǎo)入slf4j-api和對(duì)應(yīng)的綁定器。需要說(shuō)的是這個(gè)綁定器庄敛,比如導(dǎo)入了slf4j-log4j12的依賴(lài)俗壹,slf4j-log4j12會(huì)自動(dòng)導(dǎo)入log4j的依賴(lài)。所以需要排除掉應(yīng)用自己導(dǎo)入的log4j依賴(lài)藻烤。
  • 如果使用需要將jul或者jcl橋接到log4j2绷雏,除了需要導(dǎo)入log4j-apilo4j-core,還需要導(dǎo)入log4j-jullog-jcl橋接包怖亭;而如果想將log4j橋接到log4j2患亿,則只需要導(dǎo)入lo4j-corelog4j-1.2-api即可。
  • 如果要將jul橋接到log4j2考润,需要設(shè)置系統(tǒng)屬性刽沾,屬性名為java.util.logging.manager,屬性值為org.apache.logging.log4j.jul.LogManager峭跳”焐簦可以通過(guò)兩種方式設(shè)置,一是添加vm參數(shù)-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager蛀醉,二是在調(diào)用LoggerLoggerManager之前執(zhí)行System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager")悬襟。
    import java.util.logging.Logger;
    
    public class Jul {
        public static void main(String[] args) {
            System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager")。
            Logger logger = Logger.getLogger("jul");
            logger.info("jul");
        }
    }
    
  • 如果要將jul橋接到slf4j拯刁,也需要做些特殊處理將jul的日志路由到slf4j


    介紹了兩種方法:
    第一種是編程的方式脊岳,如下代碼所示
    import org.slf4j.bridge.SLF4JBridgeHandler;
    import java.util.logging.Logger;
    
    public class Jul {
        public static void main(String[] args) {
            // 移除已經(jīng)存在的handler
            SLF4JBridgeHandler.removeHandlersForRootLogger();
            // 安裝SLF4JBridgeHandler
            SLF4JBridgeHandler.install();
            Logger logger = Logger.getLogger("jul");
            logger.info("jul");
        }
    }
    

    *第二種方式是修改JAVA_HOME\jre\lib\logging.properties


  • 循環(huán)依賴(lài)
    比如應(yīng)用中加上了jul-to-slf4j和slf4j-jdk14的依賴(lài),jul會(huì)重定向到slf4j垛玻,slf4j又綁定的jul割捅,所以這樣就產(chǎn)生了循環(huán)依賴(lài)。
    下面列出一些不能會(huì)禪心循環(huán)依賴(lài)的jar依賴(lài)
    slf4j中
    jul-to-slf4j 和 jul-to-slf4j
    log4j-over-slf4j 和 slf4j-log4j12
    jcl-over-slf4j 和 slf4j-jcl
    log4j2中
    log4j-to-slf4j 和 log4j-slf4j-impl

  • 還有許多細(xì)節(jié)帚桩,比如性能呀什么的亿驾,文中沒(méi)有提到,鄉(xiāng)親們感興趣的話可以去看官網(wǎng)哦:slf4j官網(wǎng)账嚎、log4j2官網(wǎng)

??總結(jié)??:
  • 對(duì)于庫(kù)的創(chuàng)造者(上帝??)莫瞬,不寫(xiě)接口造成的后果就是------>看到上面畫(huà)的日志的各種橋接的圖你心碎嗎儡蔓,我反正碎了??。如果一開(kāi)始就定義了接口規(guī)范疼邀,我想我們的日志框架不會(huì)那么混亂喂江。
  • 對(duì)于庫(kù)的使用者,一定要面向抽象編程旁振,這樣的應(yīng)用才會(huì)健壯获询,易于擴(kuò)展。
  • 沒(méi)有什么問(wèn)題是加一個(gè)適配器層(比如各種橋接器拐袜、綁定器筐付,他們都是適配器)解決不了的,解決不了阻肿,那就兩個(gè)瓦戚。

最后感謝各位客官?????????????♂????♀?閱讀此文章??,文中可能有表述錯(cuò)誤或不準(zhǔn)確的地方丛塌,或者各種錯(cuò)別字较解,請(qǐng)留言指正??

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市赴邻,隨后出現(xiàn)的幾起案子印衔,更是在濱河造成了極大的恐慌,老刑警劉巖姥敛,帶你破解...
    沈念sama閱讀 212,718評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件奸焙,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡彤敛,警方通過(guò)查閱死者的電腦和手機(jī)与帆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)墨榄,“玉大人玄糟,你說(shuō)我怎么就攤上這事“乐龋” “怎么了阵翎?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,207評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)之剧。 經(jīng)常有香客問(wèn)我郭卫,道長(zhǎng),這世上最難降的妖魔是什么背稼? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,755評(píng)論 1 284
  • 正文 為了忘掉前任贰军,我火速辦了婚禮,結(jié)果婚禮上雇庙,老公的妹妹穿的比我還像新娘谓形。我一直安慰自己,他們只是感情好疆前,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布寒跳。 她就那樣靜靜地躺著,像睡著了一般竹椒。 火紅的嫁衣襯著肌膚如雪童太。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 50,050評(píng)論 1 291
  • 那天胸完,我揣著相機(jī)與錄音书释,去河邊找鬼。 笑死赊窥,一個(gè)胖子當(dāng)著我的面吹牛爆惧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播锨能,決...
    沈念sama閱讀 39,136評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼扯再,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了址遇?” 一聲冷哼從身側(cè)響起熄阻,我...
    開(kāi)封第一講書(shū)人閱讀 37,882評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎倔约,沒(méi)想到半個(gè)月后秃殉,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,330評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡浸剩,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評(píng)論 2 327
  • 正文 我和宋清朗相戀三年钾军,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片绢要。...
    茶點(diǎn)故事閱讀 38,789評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡巧颈,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出袖扛,到底是詐尸還是另有隱情砸泛,我是刑警寧澤,帶...
    沈念sama閱讀 34,477評(píng)論 4 333
  • 正文 年R本政府宣布蛆封,位于F島的核電站唇礁,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏惨篱。R本人自食惡果不足惜盏筐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望砸讳。 院中可真熱鬧琢融,春花似錦界牡、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,864評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至纳令,卻和暖如春挽荠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背平绩。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,099評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工圈匆, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人捏雌。 一個(gè)月前我還...
    沈念sama閱讀 46,598評(píng)論 2 362
  • 正文 我出身青樓跃赚,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親性湿。 傳聞我的和親對(duì)象是個(gè)殘疾皇子来累,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評(píng)論 2 351

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