@aloxc
2017-12-05T06:24:53.000000Z
字数 3649
阅读 559
一起学 ignite 源码分析 插件
ignite中支持我们自己定义插件【代码中已经预留了坑,但是还没拉屎,至少没拉完】,我们可以从代码中看到关于插件的一些处理流程,
1.IgniteKernal类中有下面的代码,
//本行代码是通过ServiceLoad来读取资源文件META/services/org.apache.ignite.plugin.PluginProvider中定义的插件类表,这个资源文件中的每行就是一个实现了接口PluginProvider的一个类List<PluginProvider> plugins = IgniteUtils.allPluginProviders();....//初始化ignite服务上下文,最终里面的调用MarshallerContextAdapter类的构造方法代码,见下面2中再说,ctx = new GridKernalContextImpl(log,this,cfg,gw,utilityCachePool,marshCachePool,execSvc,sysExecSvc,p2pExecSvc,mgmtExecSvc,callbackExecSvc,plugins);...//开始一个处理器来处理插件,具体分析见3中再说startProcessor(new IgnitePluginProcessor(ctx, cfg, plugins));
2.上面说的IgniteKernal中调用类GridKernalContextImpl类的构造方法,而GridKernalContextImpl类的构造方法又实例化一个MarshallerContextImpl,MarshallerContextImpl调用父类MarshallerContextAdapter中的构造方法
public MarshallerContextAdapter(@Nullable List<PluginProvider> plugins) {System.out.println("准备注册插件处理器,插件数量 = " + plugins.size());try {ClassLoader ldr = IgniteUtils.gridClassLoader();Enumeration<URL> urls = ldr.getResources(CLS_NAMES_FILE);boolean foundClsNames = false;while (urls.hasMoreElements()) {processResource(urls.nextElement());foundClsNames = true;}if (!foundClsNames)throw new IgniteException("从文件中加载类异常" +"[file=" + CLS_NAMES_FILE + ", ldr=" + ldr + ']');URL jdkClsNames = ldr.getResource(JDK_CLS_NAMES_FILE);if (jdkClsNames == null)throw new IgniteException("从文件中加载类异常" +"[file=" + JDK_CLS_NAMES_FILE + ", ldr=" + ldr + ']');processResource(jdkClsNames);checkHasClassName(GridDhtPartitionFullMap.class.getName(), ldr, CLS_NAMES_FILE);checkHasClassName(GridDhtPartitionMap2.class.getName(), ldr, CLS_NAMES_FILE);checkHasClassName(HashMap.class.getName(), ldr, JDK_CLS_NAMES_FILE);if (plugins != null && !plugins.isEmpty()) {for (PluginProvider plugin : plugins) {final String clazzProp = "META-INF/" + plugin.name().toLowerCase() + ".classnames.properties";URL pluginClsNames = ldr.getResource(clazzProp);if (pluginClsNames != null){processResource(pluginClsNames);}else{System.out.println("代码中有定义了插件" + plugin.getClass().getName() + ",但是没有对应的资源属性文件\t" + clazzProp);}}}else{System.out.println("插件为空");}}catch (IOException e) {throw new IllegalStateException("初始化调度上下文失败.", e);}}
3、startProcessor(new IgnitePluginProcessor(ctx, cfg, plugins));
先说创建实例IgnitePluginProcessor的代码,
public IgnitePluginProcessor(GridKernalContext ctx, IgniteConfiguration cfg, List<PluginProvider> providers) {super(ctx);ExtensionRegistryImpl registry = new ExtensionRegistryImpl();for (PluginProvider provider : providers) {GridPluginContext pluginCtx = new GridPluginContext(ctx, cfg);if (GridFunc.isEmpty(provider.name()))throw new IgniteException("插件名称不能为空");if (plugins.containsKey(provider.name()))throw new IgniteException("插件名称重复: " + provider.name());plugins.put(provider.name(), provider);pluginCtxMap.put(provider, pluginCtx);provider.initExtensions(pluginCtx, registry);if (provider.plugin() == null)throw new IgniteException("插件中未定义插件类,也就是" + provider.getClass() + "类中的方法plugin()未返回有效的插件");}extensions = registry.createExtensionMap();}
private void startProcessor(GridProcessor proc) throws IgniteCheckedException {ctx.add(proc);try {if (!skipDaemon(proc))proc.start();}catch (IgniteCheckedException e) {throw new IgniteCheckedException("Failed to start processor: " + proc, e);}}
本方法中,先判断下处理器是否是非守护方式运行(判断),如果不是非守护方式运行就调用当前处理器的start方法。我们现在分析的是插件处理器,那么就是执行IgnitePluginProcessor中的start方法,start中就只调用了askPluginsInfo()输出下插件信息,
private void ackPluginsInfo() {if (plugins.isEmpty()) {IgniteUtils.warn(log, " ^-- 插件为空");}else {IgniteUtils.quietAndInfo(log, "配置插件列表:");for (PluginProvider plugin : plugins.values()) {IgniteUtils.quietAndInfo(log, " ^-- " + plugin.name() + " " + plugin.version());IgniteUtils.quietAndInfo(log, " ^-- " + plugin.copyright());IgniteUtils.quietAndInfo(log, "");}}}
通篇就只有一个调用插件初始化的方法代码provider.initExtensions(pluginCtx, registry);这个方法在我们实现的插件类而已,貌似功能不强,所以插件充其量就是半拉子工程
