<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>

          日志框架Log4j的學(xué)習(xí)小記

          共 3885字,需瀏覽 8分鐘

           ·

          2021-07-17 23:35

          Java項(xiàng)目的框架基本就是slf4j,slf4j提供了一套規(guī)范,也就是門面,而至于后邊是如何實(shí)現(xiàn)的只要按照人家定義的接口去做就行了。常見的日志框架又springboot自帶的logback,還有異步的日志框架log4j,當(dāng)然還有一些大佬自己做日志框架的。這里作者大概的看了一下日志框架的代碼。稍微講解一下日志框架是怎么做的。

                  首先說的就是slf4j這個(gè)門面,之前在重構(gòu)這本書中就提到要善于抽象代碼形成主體結(jié)構(gòu)。然后在定制化的工作中進(jìn)行重載等工作,Slf4j就將日志的一般方法進(jìn)行定義。并提供了一些默認(rèn)的日志打印方法。

          public static Logger logger= LoggerFactory.getLogger("123");
          通過上述代碼,我們進(jìn)行跟蹤。

          通過對代碼的查看,這塊在獲取日志的時(shí)候首先設(shè)置采用log4j作為日志框架,如果出現(xiàn)異常則采用默認(rèn)的日志框架。

          當(dāng)項(xiàng)目中采用log4j作為日志框架的時(shí)候,getlogger如下:

          而在logmanger中的靜態(tài)方法中則進(jìn)行了日志框架配置文件的解析

          而對于方法logger.debug()來說最終走的方法也就是log4jloggerAdapter提供的debug方法。

          通過跟蹤,發(fā)現(xiàn)日志的打印采用多線程。

          通過查看代碼,我們發(fā)現(xiàn)這里打印日志的時(shí)候?qū)⑷罩緦懙絣ist列表中,然后通過Dispatcher線程將對list中的列表進(jìn)行處理。而在AsynAppender初始化的時(shí)候就將Dispatcher線程進(jìn)行啟動(dòng)。

          通過上述的代碼閱讀,我們大概了解logger的一般過程,但是我們的asynappender是什么時(shí)候添加到我們的logger對象中的?我們懷著問題找到我們當(dāng)時(shí)解析log4j.xml的文件。一直跟蹤,最后找到如下的代碼:

          基于上述解析,我們大概的說一下logger日志的基本過程。首先通過slfj是一個(gè)默認(rèn)的門面框架。一般又logback和log4j的實(shí)現(xiàn),log4j采用新線程來處理日志,所有的日志通過list進(jìn)行緩存,log4j異步線程會(huì)從list中獲取日志的內(nèi)容然后根據(jù)策略寫到不同的文件或者網(wǎng)絡(luò)接口或者控制臺(tái)等。在初始化的時(shí)候,slfj會(huì)先判斷是否存在log4j,在不存在情況下才會(huì)走默認(rèn)的其他日志框架。確認(rèn)使用log4j之后,會(huì)通過logmanager的靜態(tài)方法塊解析log4j.xml文件,并據(jù)此初始化log4j的日志線程,并啟動(dòng)該日志線程。不同的logger對應(yīng)不同的名稱,最終通過hashTable進(jìn)行緩存,當(dāng)然這塊也可以采用concurentHashMap,日志的打印通過list進(jìn)行匯總,然后日志的異步線程結(jié)合日志的策略進(jìn)行不同方式的展示。

          說到這里,可能就有一個(gè)疑問了,我們的配置文件中好像有個(gè)配置。可以指定這個(gè)log4j.xml文件的地址和名稱,如下所示,于是乎我們在之前的那個(gè)代碼寫死的是不是我們理解的不對。

          logging.config=classpath:config/log4j2.xml

          跟著代碼,我們發(fā)現(xiàn)在Spring的監(jiān)聽器中有這樣的代碼。

          private void onApplicationStartingEvent(ApplicationStartingEvent event) {//這里的logginSystem經(jīng)過這里的處理就變成了Log4J2LoggingSystem,此類中包含我們上邊說的logmanger部分,也就是解析xml的部分,也就是創(chuàng)建線程。初次之外這里的log4j2LogginSystem也是我們上次說的RunTime回調(diào)定義的地方。        this.loggingSystem = LoggingSystem.get(event.getSpringApplication().getClassLoader());//前置初始化        this.loggingSystem.beforeInitialize();    }



          //從配置文件中拿到logging.config并進(jìn)行LoggingSystem的初始化 private void initializeSystem(ConfigurableEnvironment environment, LoggingSystem system, LogFile logFile) { LoggingInitializationContext initializationContext = new LoggingInitializationContext(environment); String logConfig = environment.getProperty("logging.config"); if (this.ignoreLogConfig(logConfig)) { system.initialize(initializationContext, (String)null, logFile); } else { try { ResourceUtils.getURL(logConfig).openStream().close();//這塊在初始化的時(shí)候?qū)ε渲梦募M(jìn)行解析,并對logger進(jìn)行注冊。 system.initialize(initializationContext, logConfig, logFile); } catch (Exception var7) { System.err.println("Logging system failed to initialize using configuration from '" + logConfig + "'"); var7.printStackTrace(System.err); throw new IllegalStateException(var7); } }    }//加載配置文件 ,location為配置文件中的日志xml文件地址 protected void loadConfiguration(String location, LogFile logFile) {        Assert.notNull(location, "Location must not be null"); try {//拿到logmanger中的日志 LoggerContext ctx = this.getLoggerContext(); URL url = ResourceUtils.getURL(location); ConfigurationSource source = this.getConfigurationSource(url); ctx.start(ConfigurationFactory.getInstance().getConfiguration(ctx, source)); } catch (Exception var6) { throw new IllegalStateException("Could not initialize Log4J2 logging from " + location, var6); } }

                  這塊寫的有點(diǎn)亂,作者本人也迷迷糊糊的。想著大概的過程應(yīng)該是這樣的,但是遇到了不同的logger注冊器,有hashtable、concurentHashMap以及hashMap,有點(diǎn)亂。一句話還是沒深刻的理解吧,大概的過程咋算是大概的說了一下了。對于動(dòng)態(tài)修改日志級(jí)別的這種問題,因?yàn)槲覀兊膉ava是引用傳值,因此我們我們直接從logmanager中獲取指定名稱的logger,然后修改日志level即可。當(dāng)然日志的緩存隊(duì)列我們可以采用阻塞鏈表來做。

                 

                  由于作者水平有限,分析的不是很透徹,作者本人也是知道一個(gè)大概的方向,細(xì)節(jié)上也是迷迷糊糊,慚愧!如對大家有一定的誤導(dǎo),還望見諒!





          瀏覽 63
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  久久大鸡吧在线 | 亚洲第六页 | 人人摸人人爱人人操 | 黄色在线观看免费 | 青青操在线|