摘要:前言使用插件机制加载各种组件,本文简要分析插件机制实现注解注解提供了一种便捷的方法将一个类声明成的插件,比如,单例类用来保存插件信息,暴露了一些方法从配置文件中加载内置插件,使用了单例设计模式线程安全的数据结构使用了一些多线程编程的最佳实践
前言
log4j2 使用插件机制加载各种组件:appender, logger .etc,本文简要分析 log4j2 插件机制实现
Plugin Annotation(注解)Plugin 注解提供了一种便捷的方法将一个类声明成 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 类用来保存插件信息,暴露了一些方法从配置文件中加载(内置)插件,使用了单例设计模式
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(); } } } }线程安全的数据结构
PluginRegistry 使用了一些 Java 多线程编程的最佳实践:
使用 AtomicReference 类的 CAS(compare and set)操作,避免在多线程环境下 插件配置 被多次加载
使用 ConcurrentMapHash 类替代 HashMap 提供线程安全的 map
PluginType 类用来描述插件,比如插件对应的 class
/** * Contains plugins found in Log4j2Plugins.dat cache files in the main CLASSPATH. */ private final AtomicReference
log4j2Plugins.dat 是插件描述文件,内部插件描述文件位于:
log4j-core-2.5.jar META-INF org.apache.logging.log4j.core.config.plugins Log4j2Plugins.dat加载插件
PluginRegistry 中和加载扫描插件相关的方法
loadFromMainClassLoader,加载内部插件
loadFromBundle,osgi相关
loadFromPackage,加载指定 package(包)中的插件
加载内部插件public Map加载指定包中插件>> loadFromMainClassLoader() { final Map >> existing = pluginsByCategoryRef.get(); // 如果 get 方法返回非空,说明已经通过 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 MapPluginManager>> loadFromPackage(final String pkg) { // 参数校验 if (Strings.isBlank(pkg)) { return Collections.emptyMap(); } // 如果 pkg 已经被加载过直接返回 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 类用来加载和管理所有的插件,每一个 category(类别)都有一个对应的 PluginManager
public PluginManager(final String category) { this.category = category; }
collectPlugins 方法用于加载插件(描述信息)
public void collectPlugins(final List总结packages) { ... }
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/66792.html
摘要:前言一般都会对应用程序日志做回滚处理,本文简要分析日志回滚实现触发策略使用接口来抽象日志回滚触发策略,使用了设计模式方法用于初始化策略,方法用于判断是否需要回滚,接口的不同实现类对应不同的策略组合模式,聚合不同的策略类基于时间的回滚策略基于 前言 一般都会对应用程序日志做回滚处理,本文简要分析 log4j2 日志回滚实现 触发策略 log4j2 使用 TriggeringPolity ...
摘要:系列文章系列第一篇基础杂记系列第二篇插件机制杂记系列第三篇流程杂记前言本身并不难,他所完成的各种复杂炫酷的功能都依赖于他的插件机制。的插件机制依赖于一个核心的库,。是什么是一个类似于的的库主要是控制钩子函数的发布与订阅。 系列文章 Webpack系列-第一篇基础杂记 Webpack系列-第二篇插件机制杂记 Webpack系列-第三篇流程杂记 前言 webpack本身并不难,他所完成...
摘要:语法部分采用的是标准。那么整个播放器是怎么把播放器的加载到中的呢在的构造函数里可以看到先生成,然后初始化父类遍历属性,将中的类实例化并将对应的嵌入到的属性中,最后在的构造函数中直接挂载到标签的父级上。 video.js 源码分析(JavaScript) 组织结构 继承关系 运行机制 插件的运行机制 插件的定义 插件的运行 控制条是如何运行的 UI与JavaScript对象的...
摘要:语法部分采用的是标准。那么整个播放器是怎么把播放器的加载到中的呢在的构造函数里可以看到先生成,然后初始化父类遍历属性,将中的类实例化并将对应的嵌入到的属性中,最后在的构造函数中直接挂载到标签的父级上。 video.js 源码分析(JavaScript) 组织结构 继承关系 运行机制 插件的运行机制 插件的定义 插件的运行 控制条是如何运行的 UI与JavaScript对象的...
阅读 2322·2021-09-29 09:42
阅读 558·2021-09-06 15:02
阅读 2598·2021-09-02 15:40
阅读 2114·2019-08-30 14:23
阅读 1862·2019-08-30 13:48
阅读 1290·2019-08-26 12:01
阅读 959·2019-08-26 11:53
阅读 2142·2019-08-23 18:31