成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Log42j 源代碼分析:plugin(插件)機(jī)制

learning / 1601人閱讀

摘要:前言使用插件機(jī)制加載各種組件,本文簡(jiǎn)要分析插件機(jī)制實(shí)現(xiàn)注解注解提供了一種便捷的方法將一個(gè)類聲明成的插件,比如,單例類用來保存插件信息,暴露了一些方法從配置文件中加載內(nèi)置插件,使用了單例設(shè)計(jì)模式線程安全的數(shù)據(jù)結(jié)構(gòu)使用了一些多線程編程的最佳實(shí)踐

前言

log4j2 使用插件機(jī)制加載各種組件:appender, logger .etc,本文簡(jiǎn)要分析 log4j2 插件機(jī)制實(shí)現(xiàn)

Plugin Annotation(注解)

Plugin 注解提供了一種便捷的方法將一個(gè)類聲明成 log4j2 的插件,比如

@Plugin(name = "Console", category = "Core", elementType = "appender", printObject = true)
public final class ConsoleAppender extends
        AbstractOutputStreamAppender {
    ...
}

name,name of the plugin

category, category to place the plugin under

name of the corresponding category of elements this plugin belongs under

Plugin Registry 單例

PluginRegistry 類用來保存插件信息,暴露了一些方法從配置文件中加載(內(nèi)置)插件,使用了單例設(shè)計(jì)模式

private static volatile PluginRegistry INSTANCE;

private static final Object INSTANCE_LOCK = new Object();

private PluginRegistry() {
}

public static PluginRegistry getInstance() {
    PluginRegistry result = INSTANCE;
    if (result == null) {
        synchronized(INSTANCE_LOCK) {
            result = INSTANCE;
            if (result == null) {
                INSTANCE = result = new PluginRegistry();
            }
        }
    }
}
線程安全的數(shù)據(jù)結(jié)構(gòu)

PluginRegistry 使用了一些 Java 多線程編程的最佳實(shí)踐:

使用 AtomicReference 類的 CAS(compare and set)操作,避免在多線程環(huán)境下 插件配置 被多次加載

使用 ConcurrentMapHash 類替代 HashMap 提供線程安全的 map

PluginType 類用來描述插件,比如插件對(duì)應(yīng)的 class

    /**
     * Contains plugins found in Log4j2Plugins.dat cache files in the main CLASSPATH.
     */
    private final AtomicReference>>> pluginsByCategoryRef =
        new AtomicReference<>();

    /**
     * Contains plugins found in Log4j2Plugins.dat cache files in OSGi Bundles.
     */
    private final ConcurrentMap>>> pluginsByCategoryByBundleId =
        new ConcurrentHashMap<>();

    /**
     * Contains plugins found by searching for annotated classes at runtime.
     */
    private final ConcurrentMap>>> pluginsByCategoryByPackage =
        new ConcurrentHashMap<>();

log4j2Plugins.dat 是插件描述文件,內(nèi)部插件描述文件位于:

log4j-core-2.5.jar
    META-INF
        org.apache.logging.log4j.core.config.plugins
            Log4j2Plugins.dat
加載插件

PluginRegistry 中和加載掃描插件相關(guān)的方法

loadFromMainClassLoader,加載內(nèi)部插件

loadFromBundle,osgi相關(guān)

loadFromPackage,加載指定 package(包)中的插件

加載內(nèi)部插件
    public Map>> loadFromMainClassLoader() {
        final Map>> existing = pluginsByCategoryRef.get();
        // 如果 get 方法返回非空,說明已經(jīng)通過 main class loader 加載過插件配置
        if (existing != null) {
            // already loaded
            return existing;
        }
        // 從配置文件加載 插件配置
        final Map>> newPluginsByCategory =    
            decodeCacheFiles(Loader.getClassLoader());
        // CAS
        if (pluginsByCategoryRef.compareAndSet(null, newPluginsByCategory)) {
            return newPluginsByCategory;
        }
        return pluginsByCategoryRef.get();
    }
加載指定包中插件
public Map>> loadFromPackage(final String pkg) {
    // 參數(shù)校驗(yàn)
    if (Strings.isBlank(pkg)) {
        return Collections.emptyMap();
    }

    // 如果 pkg 已經(jīng)被加載過直接返回
    Map>> existing = pluginByCategoryByPackage.get(pkg);
    if (existing != null) {
        return existing;
    }

    // 加載 pkg

    // 線程安全的 put if absent 操作(類似 CAS)
    existing = pluginsByCategoryByPackage.putIfAbsent(pkg, newPluginsByCategory);
    if (existing != null) {
        return existing;
    }
    return newPluginsByCategory;
}
PluginManager

PluginManager 類用來加載和管理所有的插件,每一個(gè) category(類別)都有一個(gè)對(duì)應(yīng)的 PluginManager

public PluginManager(final String category) {
    this.category = category;
}

collectPlugins 方法用于加載插件(描述信息)

public void collectPlugins(final List packages) {
    ...
}
總結(jié)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/66792.html

相關(guān)文章

  • Log42j 代碼分析:日志回滾

    摘要:前言一般都會(huì)對(duì)應(yīng)用程序日志做回滾處理,本文簡(jiǎn)要分析日志回滾實(shí)現(xiàn)觸發(fā)策略使用接口來抽象日志回滾觸發(fā)策略,使用了設(shè)計(jì)模式方法用于初始化策略,方法用于判斷是否需要回滾,接口的不同實(shí)現(xiàn)類對(duì)應(yīng)不同的策略組合模式,聚合不同的策略類基于時(shí)間的回滾策略基于 前言 一般都會(huì)對(duì)應(yīng)用程序日志做回滾處理,本文簡(jiǎn)要分析 log4j2 日志回滾實(shí)現(xiàn) 觸發(fā)策略 log4j2 使用 TriggeringPolity ...

    libin19890520 評(píng)論0 收藏0
  • webpack系列-插件機(jī)制雜記

    摘要:系列文章系列第一篇基礎(chǔ)雜記系列第二篇插件機(jī)制雜記系列第三篇流程雜記前言本身并不難,他所完成的各種復(fù)雜炫酷的功能都依賴于他的插件機(jī)制。的插件機(jī)制依賴于一個(gè)核心的庫,。是什么是一個(gè)類似于的的庫主要是控制鉤子函數(shù)的發(fā)布與訂閱。 系列文章 Webpack系列-第一篇基礎(chǔ)雜記 Webpack系列-第二篇插件機(jī)制雜記 Webpack系列-第三篇流程雜記 前言 webpack本身并不難,他所完成...

    Neilyo 評(píng)論0 收藏0
  • video.js 源碼分析(JavaScript)

    摘要:語法部分采用的是標(biāo)準(zhǔn)。那么整個(gè)播放器是怎么把播放器的加載到中的呢在的構(gòu)造函數(shù)里可以看到先生成,然后初始化父類遍歷屬性,將中的類實(shí)例化并將對(duì)應(yīng)的嵌入到的屬性中,最后在的構(gòu)造函數(shù)中直接掛載到標(biāo)簽的父級(jí)上。 video.js 源碼分析(JavaScript) 組織結(jié)構(gòu) 繼承關(guān)系 運(yùn)行機(jī)制 插件的運(yùn)行機(jī)制 插件的定義 插件的運(yùn)行 控制條是如何運(yùn)行的 UI與JavaScript對(duì)象的...

    Neilyo 評(píng)論0 收藏0
  • video.js 源碼分析(JavaScript)

    摘要:語法部分采用的是標(biāo)準(zhǔn)。那么整個(gè)播放器是怎么把播放器的加載到中的呢在的構(gòu)造函數(shù)里可以看到先生成,然后初始化父類遍歷屬性,將中的類實(shí)例化并將對(duì)應(yīng)的嵌入到的屬性中,最后在的構(gòu)造函數(shù)中直接掛載到標(biāo)簽的父級(jí)上。 video.js 源碼分析(JavaScript) 組織結(jié)構(gòu) 繼承關(guān)系 運(yùn)行機(jī)制 插件的運(yùn)行機(jī)制 插件的定義 插件的運(yùn)行 控制條是如何運(yùn)行的 UI與JavaScript對(duì)象的...

    simpleapples 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<