graylog 的PluginModule 可以简化graylog 插件的开发,方便我们进行扩展
参考功能
- 类结构
从下图可以看出是依赖了guice 进行的包装,代码中好多都是支持依赖PluginModule开发的,PluginModule 提供了功能模块bean 的注册
- 包含的能力
从下图可以看出,提供的功能还是不少的,核心都是关于bean 注册的,利用了guice 的多bena binding,包含了消息处理,权限处理,通道处理,编码处理等功能
PluginModule 的使用
PluginModule 是有Plugin 接口实现使用的,如下图
插件的加载
插件加载并没有多少太复杂的东西,基于了spi 处理
- 参考代码
public Set<Plugin> loadPlugins() {
return ImmutableSortedSet.orderedBy(new PluginComparator())
.addAll(Iterables.transform(loadJarPlugins(), new PluginAdapterFunction()))
.addAll(Iterables.transform(loadClassPathPlugins(), new PluginAdapterFunction()))
.build();
}
return ImmutableSortedSet.orderedBy(new PluginComparator())
以上包含了基于jar 的以及classpath 的,同时也进行了类隔离的处理(包含共享以及独立)
final List<URL> sharedClassLoaderUrls = new ArrayList<>();
urls.forEach(url -> {
final PluginProperties properties = PluginProperties.fromJarFile(url.getFile());
// Decide whether to create a separate, isolated class loader for the plugin. When the plugin is isolated
// (the default), it gets its own class loader and cannot see other plugins. Plugins which are not
// isolated share one class loader so they can see each other. (makes plugin inter-dependencies work)
if (properties.isIsolated()) {
LOG.debug("Creating isolated class loader for <{}>", url);
classLoader.addClassLoader(URLClassLoader.newInstance(new URL[]{url}));
} else {
LOG.debug("Using shared class loader for <{}>", url);
sharedClassLoaderUrls.add(url);
}
});
// Only create the shared class loader if any plugin requests to be shared.
if (!sharedClassLoaderUrls.isEmpty()) {
LOG.debug("Creating shared class loader for {} plugins: {}", sharedClassLoaderUrls.size(), sharedClassLoaderUrls);
classLoader.addClassLoader(URLClassLoader.newInstance(sharedClassLoaderUrls.toArray(new URL[0])));
}
final ServiceLoader<Plugin> pluginServiceLoader = ServiceLoader.load(Plugin.class, classLoader);
return ImmutableSet.copyOf(pluginServiceLoader);
urls.forEach(url -> {
说明
graylog 一开guice 进行插件化的处理,使用比较方便,包装的功能丰富