最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

關(guān)于slf4j_log4j2源碼學(xué)習(xí)心得

 更新時(shí)間:2021年12月22日 10:34:17   作者:會(huì)灰翔的灰機(jī)  
這篇文章主要介紹了slf4j_log4j2源碼學(xué)習(xí)心得,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

日志工廠獲取Logger

slf4j_getLogger.jpg

獲取日志工廠_getILoggerFactory_

執(zhí)行初始化performInitialization

綁定工廠bind

查找可能被綁定的StaticLoggerBinder類路徑findPossibleStaticLoggerBinderPathSet

如果LoggerFactory類加載器為空則使用System類加載器,如果System類加載器為空則使用Bootstrap類加載器加載讀取org/slf4j/impl/StaticLoggerBinder.class類資源路徑

如果LoggerFactory類加載器不為空,使用loggerFactoryClassLoader類加載器讀取org/slf4j/impl/StaticLoggerBinder.class類資源路徑

獲取StaticLoggerBinder單例_SINGLETON_

打印實(shí)際綁定的StaticLoggerBInder實(shí)例,標(biāo)識(shí)初始化成功

此時(shí)日志工廠已經(jīng)完成初始化,創(chuàng)建日志代替者工廠SubstituteLoggerFactory,獲取替代者工廠中的Loggers遍歷其名稱從日志工廠中獲取相應(yīng)的Logger,將Logger設(shè)置為替代者委派對(duì)象setDelegate

重新播放替代者工廠事件隊(duì)列中的事件

清楚替代者工廠事件隊(duì)列,日志列表

使用StaticLoggerBinder獲取日志工廠,log4j2的綁定著實(shí)現(xiàn)返回Log4jLoggerFactory

日志工廠中獲取Logger,先獲取日志上下文,從日志上下文中獲取Logger

根據(jù)日志配置屬性log4j2.loggerContextFactory獲取日志上下文工廠

不存在日志上下文工廠配置則使用ProviderUtil提供者工具類讀取SPI配置默認(rèn)為L(zhǎng)og4jContextFactory

日志上下文工廠構(gòu)造器中創(chuàng)建日志上下文選擇器createContextSelector,根據(jù)Log4jContextSelector屬性配置獲取日志上下文選擇器實(shí)現(xiàn),假定為異步實(shí)現(xiàn):AsyncLoggerContextSelector

日志上下文工廠使用日志上下文選擇器創(chuàng)建日志上下文AsyncLoggerContext,日志上下文構(gòu)造器中創(chuàng)建AsyncLoggerDisruptor

如果日志上下文處于初始化狀態(tài),啟動(dòng)日志上下文,啟動(dòng)日志上下文中的loggerDisruptor

啟動(dòng)Disruptor

計(jì)算ringBufferSize,如果啟用了Threadlocals(log4j2.enable.threadlocals)則默認(rèn)4k,否則256k,讀取AsyncLogger.RingBufferSize屬性配置;如果size小于128則使用128修正

創(chuàng)建等待策略,如果屬性名稱以AsyncLogger.開(kāi)頭,讀取AsyncLogger.Timeout,否則讀取AsyncLoggerConfig.Timeout配置的超時(shí)時(shí)間,默認(rèn)為10毫秒;讀取AsyncLogger.WaitStrategy屬性配置的策略類型,默認(rèn)為TIMEOUT,根據(jù)類型創(chuàng)建等待策略,默認(rèn)為超時(shí)類型:TimeoutBlockingWaitStrategy

創(chuàng)建單線程線程池_newSingleThreadExecutor_

創(chuàng)建異步隊(duì)列滿的處理策略AsyncQueueFullPolicyFactory.create,讀取log4j2.AsyncQueueFullPolicy策略配置,默認(rèn)策略為同步阻塞DefaultAsyncQueueFullPolicy,Discard類型為DiscardingAsyncQueueFullPolicy,否則讀取用戶自定義策略,獲取類路徑上的AsyncQueueFullPolicy實(shí)現(xiàn)類

創(chuàng)建Disruptor實(shí)例

為Disruptor實(shí)例綁定ExceptionHandler,讀取AsyncLogger.ExceptionHandler屬性配置加載實(shí)現(xiàn)類,默認(rèn)為AsyncLoggerDefaultExceptionHandler

為Disruptor實(shí)例綁定事件handler:RingBufferLogEventHandler

啟動(dòng)Disruptor

提交線程BatchEventProcessor至線程池

向序列屏障提交序列號(hào)申請(qǐng)并等待,等待策略默認(rèn)為Timeout,超時(shí)處理后進(jìn)行線程yield資源釋放

獲取到有效序列號(hào)根據(jù)序列號(hào)獲取數(shù)據(jù)RingBufferLogEvent

回調(diào)事件handle實(shí)例記錄日志RingBufferLogEventHandler.onEvent

執(zhí)行事件RingBufferLogEvent.execute(異步寫(xiě)日志)

啟動(dòng)父類日志上下文LoggerContext.start(),重新加載配置reconfigure,設(shè)置配置setConfiguration,啟動(dòng)配置config.start();

map.putIfAbsent("contextName", contextName);
config.start();
this.configuration = config;
  • 由日志上下文中獲取日志getLogger,不存在則創(chuàng)建日志AsyncLogger
  • 返回異步日志實(shí)例

日志輸出Logger.info

slf4j_AsyncLogger.jpg

日志打印logger.info

MessageFactory2將字符串日志封裝為Message實(shí)例:ParameterizedMessageFactory.newMessage

從緩存中獲取RingBuffer日志事件轉(zhuǎn)換器:AsyncLogger.logWithThreadLocalTranslator.getCachedTranslator

初始化RingBuffer日志事件轉(zhuǎn)換器:AsyncLogger.initTranslator,RingBufferLogEventTranslator.setBasicValues設(shè)置基礎(chǔ)值

發(fā)布日志事件轉(zhuǎn)換器:RingBufferLogEventTranslator

異步日志Disruptor嘗試發(fā)布tryPublish

Disruptor獲取RingBuffer嘗試發(fā)布

轉(zhuǎn)換器將日志數(shù)據(jù)轉(zhuǎn)換為日志事件:RingBufferLogEventTranslator.translateTo

根據(jù)序號(hào)sequence獲取對(duì)應(yīng)的事件實(shí)例RingBufferLoggerEvent并將轉(zhuǎn)換器中的數(shù)據(jù)寫(xiě)入RingBufferLoggerEvent.setValues

發(fā)布消息序列號(hào)MultiProducerSequencer

等待策略發(fā)送喚醒信號(hào)TimeoutBlockingWaitStrategy.signalAllWhenBlocking

異步日志寫(xiě)入

slf4j_writeLogger.jpg

BatchEventProcessor.eventHandler.onEvent->RingBufferLogEventHandler.onEvent->執(zhí)行事件RingBufferLogEvent.execute

執(zhí)行異步日志寫(xiě)入當(dāng)前事件消息actualAsyncLog(this)

從可靠性策略工廠中獲取可靠性策略,根據(jù)參數(shù)配置獲取:log4j.ReliabilityStrategy,默認(rèn)AwaitCompletion:AwaitCompletionReliabilityStrategy,寫(xiě)入日志strategy.log(AsyncLogger, event);

可靠性策略獲取活躍的LoggerConfig,如果沒(méi)取到,遞歸AsyncLogger的next節(jié)點(diǎn)獲取

LoggerConfig寫(xiě)入日志log,走過(guò)濾器鏈過(guò)濾事件之后處理事件processLogEvent

調(diào)用Appender:callAppenders

調(diào)用AsyncLoggerConfigDisruptor的tryEnqueue,準(zhǔn)備事件,將事件封裝為L(zhǎng)og4jLogEvent綁定至Log4jEventWrapper.event然后嘗試發(fā)布

事件handle處理事件Log4jEventWrapperHandler.onEvent

異步調(diào)用Appender:asyncCallAppenders,調(diào)用父類callAppenders

遍歷AppenderControl調(diào)用callAppender,調(diào)用callAppenderPreventRecursion

嘗試appender tryCallAppender

調(diào)用Appender追加方法append追加日志,假定為RollingRandomAccessFileAppender配置實(shí)現(xiàn),調(diào)用父類tryAppend

讀取log4j2.enable.direct.encoders配置是否直接編譯,默認(rèn)為true,直接編譯事件directEncodeEvent

獲取布局Layout編譯事件encode,假定為PatternLayout配置實(shí)現(xiàn)

如果布局的事件序列化類型eventSerializer不是Serializer2,調(diào)用父類encode,否則繼續(xù)

從threadlocal中獲取StringBuilder,不存在則創(chuàng)建,如果超出最大值則trim至最大值,最大值配置:log4j.layoutStringBuilder.maxSize,默認(rèn)為2*1024,stringbuilder設(shè)置length為0

將事件序列化后放入StringBuilder:toSerializable

獲取StringBuilder編譯器編譯StringBuilder至ByteBufferDestination

manager刷新flush,刷新至目的地,假定為RollingRandomAccessFileManager配置實(shí)現(xiàn),寫(xiě)入目標(biāo)文件

至此寫(xiě)入日志完成

異步日志上下文選擇

通過(guò)管理器獲取日志上下文LogManager.getContext(false)

public static LoggerContext getContext(final boolean currentContext) {
    // TODO: would it be a terrible idea to try and find the caller ClassLoader here?
    try {
        return factory.getContext(FQCN, null, null, currentContext, null, null);
    } catch (final IllegalStateException ex) {
        LOGGER.warn(ex.getMessage() + " Using SimpleLogger");
        return new SimpleLoggerContextFactory().getContext(FQCN, null, null, currentContext, null, null);
    }
}

上下文根據(jù)選擇器選擇獲取,我們假定是AsyncLoggerContextSelector類型,獲取方式是其超類ClassLoaderContextSelector提供getContext實(shí)現(xiàn)

可以看到只傳了一個(gè)參數(shù)currentContext,如果為true則會(huì)根據(jù)ContextAnchor.THREAD_CONTEXT當(dāng)前線程對(duì)應(yīng)的上下文,如果為空則獲取默認(rèn)的上下文DEFAULT_CONTEXT,如果默認(rèn)為空則會(huì)創(chuàng)建并緩存

如果currentContext為false則會(huì)選擇一個(gè)最匹配的恰當(dāng)?shù)纳舷挛姆祷?,如果ClassLoader不為空則按照指定的ClassLoader定位選擇locateContext。否則按照當(dāng)前的調(diào)用類的classloader進(jìn)行定位選擇

public LoggerContext getContext(final String fqcn, final ClassLoader loader, final boolean currentContext,
            final URI configLocation) {
        if (currentContext) {
            final LoggerContext ctx = ContextAnchor.THREAD_CONTEXT.get();
            if (ctx != null) {
                return ctx;
            }
            return getDefault();
        } else if (loader != null) {
            return locateContext(loader, configLocation);
        } else {
            final Class<?> clazz = StackLocatorUtil.getCallerClass(fqcn);
            if (clazz != null) {
                return locateContext(clazz.getClassLoader(), configLocation);
            }
            final LoggerContext lc = ContextAnchor.THREAD_CONTEXT.get();
            if (lc != null) {
                return lc;
            }
            return getDefault();
        }
    }

locateContext定位選擇日志上下文

根據(jù)classloader的hashcode值獲取對(duì)應(yīng)的日志上下文,異步選擇器實(shí)現(xiàn)添加了前綴

@Override
    protected String toContextMapKey(final ClassLoader loader) {
        // LOG4J2-666 ensure unique name across separate instances created by webapp classloaders
        return "AsyncContext@" + Integer.toHexString(System.identityHashCode(loader));
    }

如果對(duì)應(yīng)的日志上下文為空則創(chuàng)建并緩存

如果configLocation為空則遍歷classloader的父classloader獲取對(duì)應(yīng)的日志上下文返回,如果不存在則繼續(xù)創(chuàng)建

如果configLocation不為空則直接根據(jù)configLocation創(chuàng)建日志上下文并按照classloader的hashcode值拼接的名稱緩存至CONTEXT_MAP

如果CONTEXT_MAP緩存存在對(duì)應(yīng)的日志上下文,并且不為空,則會(huì)判斷configLocation是否一致equals方法,如果不一致則更新后返回

如果CONTEXT_MAP緩存存在對(duì)應(yīng)的日志上下文,并且為空,則創(chuàng)建日志上下文以及日志上下文的弱引用WeakReference并緩存至

總結(jié)

對(duì)于異步日志,如果includeLocation沒(méi)有指定,默認(rèn)是關(guān)閉的狀態(tài),也就是不會(huì)記錄日志調(diào)用時(shí)的堆棧位置信息:LoggerConfig.includeLocation。

如果記錄日志時(shí)存在Throwable對(duì)象,則會(huì)記錄至RingBufferLogEventTranslator.thrown。

thrown在日志事件反序列化后為null,thrownProxy可能不為null,thrownProxy是thrown的代理,即使用thrown為入?yún)?gòu)造的代理實(shí)例

    // Note: for asynchronous loggers, includeLocation default is FALSE,
    // for synchronous loggers, includeLocation default is TRUE.
    protected static boolean includeLocation(final String includeLocationConfigValue) {
        if (includeLocationConfigValue == null) {
            final boolean sync = !AsyncLoggerContextSelector.isSelected();
            return sync;
        }
        return Boolean.parseBoolean(includeLocationConfigValue);
    }

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 淺談多線程_讓程序更高效的運(yùn)行

    淺談多線程_讓程序更高效的運(yùn)行

    下面小編就為大家?guī)?lái)一篇淺談多線程_讓程序更高效的運(yùn)行。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-10-10
  • Maven下載依賴的順序及配置文件小結(jié)

    Maven下載依賴的順序及配置文件小結(jié)

    本文主要介紹了Maven下載依賴的順序及配置文件小結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • java LeetCode題解KMP算法示例

    java LeetCode題解KMP算法示例

    這篇文章主要為大家介紹了java LeetCode題解KMP算法示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10
  • BufferedReader中read()方法和readLine()方法的使用

    BufferedReader中read()方法和readLine()方法的使用

    這篇文章主要介紹了BufferedReader中read()方法和readLine()方法的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • Seata?AT模式TM處理流程圖文示例詳解

    Seata?AT模式TM處理流程圖文示例詳解

    這篇文章主要為大家介紹了Seata?AT模式TM處理流程圖文示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • 查看本地啟動(dòng)SpringBoot的本地端口號(hào)的幾種方式

    查看本地啟動(dòng)SpringBoot的本地端口號(hào)的幾種方式

    這篇文章主要介紹了查看本地啟動(dòng)SpringBoot的本地端口號(hào)的幾種方式,文中通過(guò)代碼示例講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-10-10
  • 常用的Java數(shù)據(jù)結(jié)構(gòu)知識(shí)點(diǎn)匯總

    常用的Java數(shù)據(jù)結(jié)構(gòu)知識(shí)點(diǎn)匯總

    這篇文章主要介紹了常用的Java數(shù)據(jù)結(jié)構(gòu)知識(shí)點(diǎn)匯總,數(shù)據(jù)結(jié)構(gòu)分線性數(shù)據(jù)結(jié)構(gòu)和非線性數(shù)據(jù)結(jié)構(gòu),下面對(duì)此作詳細(xì)介紹,需要的小伙伴可以參考一下,希望對(duì)你的學(xué)習(xí)或工作有所幫助
    2022-03-03
  • SpringMVC中的@RequestMapping注解解析

    SpringMVC中的@RequestMapping注解解析

    這篇文章主要介紹了SpringMVC中的@RequestMapping注解解析,SpringMVC使用@RequestMapping注解為控制器指定可以處理哪些?URL?請(qǐng)求,在控制器的類定義及方法定義處都可標(biāo)注@RequestMapping,需要的朋友可以參考下
    2023-12-12
  • IDEA+Maven搭建Spring環(huán)境的詳細(xì)教程

    IDEA+Maven搭建Spring環(huán)境的詳細(xì)教程

    這篇文章主要介紹了IDEA+Maven搭建Spring環(huán)境的詳細(xì)教程,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • SpringBoot Cache緩存概念講解

    SpringBoot Cache緩存概念講解

    這篇文章主要介紹了Springboot cache緩存,使用緩存最關(guān)鍵的一點(diǎn)就是保證緩存與數(shù)據(jù)庫(kù)的數(shù)據(jù)一致性,本文給大家介紹最常用的緩存操作模式,對(duì)Springboot cache緩存操作流程感興趣的朋友一起看看吧
    2022-12-12

最新評(píng)論

济南市| 黄浦区| 从江县| 淮北市| 珠海市| 商河县| 开远市| 延安市| 苍梧县| 绥滨县| 昌宁县| 宿迁市| 鲁甸县| 东港市| 梨树县| 溆浦县| 东乌珠穆沁旗| 英吉沙县| 鱼台县| 家居| 桐庐县| 江口县| 福建省| 志丹县| 朝阳区| 司法| 伊金霍洛旗| 绥化市| 安仁县| 隆回县| 大余县| 桓台县| 车险| 丁青县| 桃江县| 灵石县| 芦山县| 屏南县| 天台县| 若羌县| 广德县|