@aloxc
2017-12-05T06:24:53.000000Z
字数 3649
阅读 514
一起学
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);这个方法在我们实现的插件类而已,貌似功能不强,所以插件充其量就是半拉子工程