node在初始化时,会创建PluginsService对象。

this.pluginsService = new PluginsService(tmpSettings, initialEnvironment.configFile(), initialEnvironment.modulesFile(),initialEnvironment.pluginsFile(), classpathPlugins);

参数包含modules目录,plugins目录。PluginsService构造函数中完成对modules目录、plugins目录下插件的加载 。

  • 扫描插件文件下的plugin-descriptor.properties文件,加载生成PluginInfo。plugin-descriptor.properties文件有一些必须的属性,如name, description, version, elasticsearch.version,java.version,还包含非必需属性,如extend.plugins,has.native.controller,type, classname, java.opts,licensed, 不能包含其它属性。
  • 扫描插件文件夹下的jar文件 ,加载生成url
  • 利用反射机制生成ClassLoader,加载Class, 初始化Plugin

生成PluginInfo

public static PluginInfo readFromProperties(final Path path) throws IOException {final Path descriptor = path.resolve(ES_PLUGIN_PROPERTIES);final Map<String, String> propsMap;{final Properties props = new Properties();try (InputStream stream = Files.newInputStream(descriptor)) {props.load(stream);}propsMap = props.stringPropertyNames().stream().collect(Collectors.toMap(Function.identity(), props::getProperty));}final String name = propsMap.remove("name");if (name == null || name.isEmpty()) {throw new IllegalArgumentException("property [name] is missing in [" + descriptor + "]");}final String description = propsMap.remove("description");if (description == null) {throw new IllegalArgumentException("property [description] is missing for plugin [" + name + "]");}final String version = propsMap.remove("version");if (version == null) {throw new IllegalArgumentException("property [version] is missing for plugin [" + name + "]");}final String esVersionString = propsMap.remove("elasticsearch.version");if (esVersionString == null) {throw new IllegalArgumentException("property [elasticsearch.version] is missing for plugin [" + name + "]");}final Version esVersion = Version.fromString(esVersionString);final String javaVersionString = propsMap.remove("java.version");if (javaVersionString == null) {throw new IllegalArgumentException("property [java.version] is missing for plugin [" + name + "]");}JarHell.checkVersionFormat(javaVersionString);final String extendedString = propsMap.remove("extended.plugins");final List<String> extendedPlugins;if (extendedString == null) {extendedPlugins = Collections.emptyList();} else {extendedPlugins = Arrays.asList(Strings.delimitedListToStringArray(extendedString, ","));}final boolean hasNativeController = parseBooleanValue(name, "has.native.controller", propsMap.remove("has.native.controller"));final PluginType type = getPluginType(name, propsMap.remove("type"));final String classname = getClassname(name, type, propsMap.remove("classname"));final String javaOpts = propsMap.remove("java.opts");if (type != PluginType.BOOTSTRAP && Strings.isNullOrEmpty(javaOpts) == false) {throw new IllegalArgumentException("[java.opts] can only have a value when [type] is set to [bootstrap] for plugin [" + name + "]");}boolean isLicensed = parseBooleanValue(name, "licensed", propsMap.remove("licensed"));if (propsMap.isEmpty() == false) {throw new IllegalArgumentException("Unknown properties for plugin [" + name + "] in plugin descriptor: " + propsMap.keySet());}return new PluginInfo(name, description, version, esVersion, javaVersionString,classname, extendedPlugins, hasNativeController, type, javaOpts, isLicensed);}

生成Bundle

static Set<Bundle> getModuleBundles(Path modulesDirectory) throws IOException {return findBundles(modulesDirectory, "module");}private static Set<Bundle> findBundles(final Path directory, String type) throws IOException {final Set<Bundle> bundles = new HashSet<>();for (final Path plugin : findPluginDirs(directory)) {final Bundle bundle = readPluginBundle(plugin, type);if (bundles.add(bundle) == false) {throw new IllegalStateException("duplicate " + type + ": " + bundle.plugin);}if (type.equals("module") && bundle.plugin.getName().startsWith("test-") && Build.CURRENT.isSnapshot() == false) {throw new IllegalStateException("external test module [" + plugin.getFileName() + "] found in non-snapshot build");}}logger.trace(() -> "findBundles("+ type+ ") returning: "+ bundles.stream().map(b -> b.plugin.getName()).sorted().collect(Collectors.toList()));return bundles;}Bundle(PluginInfo plugin, Path dir) throws IOException {this.plugin = Objects.requireNonNull(plugin);Set<URL> urls = new LinkedHashSet<>();// gather urls for jar filestry (DirectoryStream<Path> jarStream = Files.newDirectoryStream(dir, "*.jar")) {for (Path jar : jarStream) {// normalize with toRealPath to get symlinks out of our hairURL url = jar.toRealPath().toUri().toURL();if (urls.add(url) == false) {throw new IllegalStateException("duplicate codebase: " + url);}}}this.urls = Objects.requireNonNull(urls);}

加载Bundle

private List<Tuple<PluginInfo,Plugin>> loadBundles(Set<Bundle> bundles) {List<Tuple<PluginInfo, Plugin>> plugins = new ArrayList<>();Map<String, Plugin> loaded = new HashMap<>();Map<String, Set<URL>> transitiveUrls = new HashMap<>();List<Bundle> sortedBundles = sortBundles(bundles);for (Bundle bundle : sortedBundles) {if (bundle.plugin.getType() != PluginType.BOOTSTRAP) {checkBundleJarHell(JarHell.parseClassPath(), bundle, transitiveUrls);final Plugin plugin = loadBundle(bundle, loaded);plugins.add(new Tuple<>(bundle.plugin, plugin));}}loadExtensions(plugins);return Collections.unmodifiableList(plugins);}private Plugin loadBundle(Bundle bundle, Map<String, Plugin> loaded) {String name = bundle.plugin.getName();verifyCompatibility(bundle.plugin);// collect loaders of extended pluginsList<ClassLoader> extendedLoaders = new ArrayList<>();for (String extendedPluginName : bundle.plugin.getExtendedPlugins()) {Plugin extendedPlugin = loaded.get(extendedPluginName);assert extendedPlugin != null;if (ExtensiblePlugin.class.isInstance(extendedPlugin) == false) {throw new IllegalStateException("Plugin [" + name + "] cannot extend non-extensible plugin [" + extendedPluginName + "]");}extendedLoaders.add(extendedPlugin.getClass().getClassLoader());}// create a child to load the plugin in this bundleClassLoader parentLoader = PluginLoaderIndirection.createLoader(getClass().getClassLoader(), extendedLoaders);ClassLoader loader = URLClassLoader.newInstance(bundle.urls.toArray(new URL[0]), parentLoader);// reload SPI with any new services from the pluginreloadLuceneSPI(loader);ClassLoader cl = Thread.currentThread().getContextClassLoader();try {// Set context class loader to plugin's class loader so that plugins// that have dependencies with their own SPI endpoints have a chance to load// and initialize them appropriately.AccessController.doPrivileged((PrivilegedAction<Void>) () -> {Thread.currentThread().setContextClassLoader(loader);return null;});Class<? extends Plugin> pluginClass = loadPluginClass(bundle.plugin.getClassname(), loader);if (loader != pluginClass.getClassLoader()) {throw new IllegalStateException("Plugin [" + name + "] must reference a class loader local Plugin class ["+ bundle.plugin.getClassname()+ "] (class loader [" + pluginClass.getClassLoader() + "])");}Plugin plugin = loadPlugin(pluginClass, settings, configPath);loaded.put(name, plugin);return plugin;} finally {AccessController.doPrivileged((PrivilegedAction<Void>) () -> {Thread.currentThread().setContextClassLoader(cl);return null;});}}private Plugin loadPlugin(Class<? extends Plugin> pluginClass, Settings settings, Path configPath) {final Constructor<?>[] constructors = pluginClass.getConstructors();if (constructors.length == 0) {throw new IllegalStateException("no public constructor for [" + pluginClass.getName() + "]");}if (constructors.length > 1) {throw new IllegalStateException("no unique public constructor for [" + pluginClass.getName() + "]");}final Constructor<?> constructor = constructors[0];if (constructor.getParameterCount() > 2) {throw new IllegalStateException(signatureMessage(pluginClass));}final Class<?>[] parameterTypes = constructor.getParameterTypes();try {if (constructor.getParameterCount() == 2 && parameterTypes[0] == Settings.class && parameterTypes[1] == Path.class) {return (Plugin)constructor.newInstance(settings, configPath);} else if (constructor.getParameterCount() == 1 && parameterTypes[0] == Settings.class) {return (Plugin)constructor.newInstance(settings);} else if (constructor.getParameterCount() == 0) {return (Plugin)constructor.newInstance();} else {throw new IllegalStateException(signatureMessage(pluginClass));}} catch (final ReflectiveOperationException e) {throw new IllegalStateException("failed to load plugin class [" + pluginClass.getName() + "]", e);}}

es中的Plugin机制相关推荐

  1. Kubernetes的Device Plugin机制源码解析

    简介: Kubernetes 1.8 引入的Device Plugin机制,通过扩展的方式实现支持GPU.FPGA.高性能 NIC.InfiniBand等各种设备的集成.而Device Manager ...

  2. 数据库概述09(数据库中的锁机制)

    Innodb中的锁机制 使用数据库的目的在于数据共享,需要考虑数据并发访问问题.解决方案就是锁机制 锁主要包括全局锁.表锁.行锁.乐观锁和悲观锁,需要解决的问题是死锁 存储引擎 存储引擎定义MySQL ...

  3. ES 中时间日期类型 “yyyy-MM-dd HHmmss” 的完全避坑指南

    文章目录 1.ES中的日期类型有何不同 2.案例 2.1 案例介绍 2.2 原理揭秘 3.路为何这么不平 4.又一个坑 5.总结 6.ES 的时间类型为什么这么难用,有没有什么办法可以解决? 7.更优 ...

  4. ES 中时间日期类型 “yyyy-MM-dd HH:mm:ss” 的完全避坑指南

    文章目录 1.ES中的日期类型有何不同 2.案例 2.1 案例介绍 2.2 原理揭秘 3.路为何这么不平 4.又一个坑 5.总结 6.ES 的时间类型为什么这么难用,有没有什么办法可以解决? 7.更优 ...

  5. doc es 中type_Elasticsearch基础——概念和基本API操作

    Elasticsearch 版本为 7.1.0 ,本文的讲解都是基于该版本 文章中Elasticsearch将使用简称ES代替 一.基本概念 文档--Document ES是面向文档的搜索,文档是ES ...

  6. java post和put的区别,ES 中的 POST 和 PUT 的区别

    0.什么是Restful架构 比较难说清楚,这部分大雾状态,引ruanyf 理解RESTful架构 的几句总结吧: Fielding将他对互联网软件的架构原则,定名为REST,即Representat ...

  7. ES中如何实现对查询结果的二次排序

    一.场景说明 比如我们在CSDN中根据输入的关键词搜索博客文章,需要先根据关键词的相似度匹配排序,然后根据博客热度进行二次排序,保证热度比较高的博客文章优先被搜索到,提高用户的搜索体验. 那么,如何在 ...

  8. ES中数据流Data streams详解

    一.什么是数据流 官方定义: Data streams 数据流 数据流是可以跨多个索引存储仅限于追加存储的时间序列数据,同时为请求提供单个命名资源. 在 Elasticsearch 7.9之前,通常会 ...

  9. 「前端面试题系列7」Javascript 中的事件机制(从原生到框架)

    前言 这是前端面试题系列的第 7 篇,你可能错过了前面的篇章,可以在这里找到: 理解函数的柯里化 ES6 中箭头函数的用法 this 的原理以及用法 伪类与伪元素的区别及实战 如何实现一个圣杯布局? ...

最新文章

  1. C#的修饰符作用的范围
  2. html弹出窗口加载别的页面地址,仿layer.open打开新窗口URL,自适应URL页面高度
  3. java gzip 多个文件_Java Zip多文件压缩和 GZIP压缩
  4. php 将多个数组 相同的键重组,PHP – 合并两个类似于array_combine但具有重复键的数组...
  5. 【Flink】Flink 时间之 timerService().registerEventTimeTimer 主要做了什么
  6. 最新Keil MDK 5.37下载
  7. IIC,RS485,RS232各种协议手册更新中
  8. 告别晦涩难懂的物理,《张朝阳的物理课》了解一下
  9. 计算机编程课是学什么的,编程是什么课程
  10. C语言:解一元二次方程
  11. 2022到2023基于java+微信小程序毕业设计课题参考
  12. PTA】{10-1 结构拓展实验,函数}6-3 求某学生8门课的平均分 (10 分)
  13. CUDA:两种自适应图像去噪技术KNN和NLM的实例
  14. windows重要信息(键盘、鼠标、计时器)
  15. Python入门及技术指南
  16. 岁月沧桑景,浮世微语情
  17. 【原创】操作系统---文件系统设计(三)(你们需要的源代码)
  18. 生活随记 - 金子总会发光
  19. [zkaq靶场]逻辑漏洞--支付漏洞
  20. 高效生成均匀分布的点:快速泊松碟采样算法实现(Fast Poisson Disc Sampling)

热门文章

  1. 怎么查询网站的收录量
  2. mysql 二进制日志后缀数字最大为多少
  3. 梦有感 2009-10
  4. 5、在secureCRT中vi显色
  5. 深入研究display:inline-block在浏览器中的应用
  6. 南京信息工程大学滨江学院计算机科学与技术专业,南京信息工程大学滨江学院有哪些专业及什么专业好...
  7. python3安装pip3-python3安装pip3
  8. python下载不了-python安装不了
  9. python使用界面-用python编写简单ui界面窗口
  10. python怎么安装matplotlib-python 安装matplotlib