从plugin路径中读取依赖并构造对象——Azkaban源码解读之Alert plugin实现(一)

第一步加载类路径:azkaban.executor.AlerterHolder
allAlerters 是一个HashMap ,key为String,value为Alerter
mailAlerter是系统内置的,无需处理,这里要加载的是自定义的插件告警
这里边读取配置信息里的alerter.plugin.dir作为pluginDir,也就是插件文件夹
然后调用了方法loadPluginAlerters(pluginDir)

private Map<String, Alerter> loadAlerters(final Props props, final Emailer mailAlerter) {
  final Map<String, Alerter> allAlerters = new HashMap<>();
  // load built-in alerters
  allAlerters.put("email", mailAlerter);
  // load all plugin alerters
  final String pluginDir = props.getString("alerter.plugin.dir", "plugins/alerter");
  allAlerters.putAll(loadPluginAlerters(pluginDir));
  return allAlerters;
}

第二步我们追踪loadPluginAlerters(pluginDir)
这里边有一个方法需要注意:

  • Class<?> alerterClass =
    PluginUtils.getPluginClass(pluginClass, pluginDir, extLibClassPaths, parentLoader);

这个方法我们将在第二部分解析。

private Map<String, Alerter> loadPluginAlerters(final String pluginPath) {
  final File alerterPluginPath = new File(pluginPath);
  //如果文件不存在 直接返回一个空集合
  if (!alerterPluginPath.exists()) {
    return Collections.<String, Alerter>emptyMap();
  }

  final Map<String, Alerter> installedAlerterPlugins = new HashMap<>();
  //获取父类加载器
  final ClassLoader parentLoader = getClass().getClassLoader();
  //获取插件目录下的所有文件
  final File[] pluginDirs = alerterPluginPath.listFiles();
  final ArrayList<String> jarPaths = new ArrayList<>();
  //遍历所有插件目录下的所有文件
  for (final File pluginDir : pluginDirs) {
    // load plugin properties
    // 读取配置文件pluginDir下的自定义alert文件夹中的con目录下的plugin.properties
    final Props pluginProps = PropsUtils.loadPluginProps(pluginDir);
    if (pluginProps == null) {
      continue;
    }
//如果获取到配置文件,则读取如下三个配置信息
    final String pluginName = pluginProps.getString("alerter.name");
    final List<String> extLibClassPaths =
        pluginProps.getStringList("alerter.external.classpaths",
            (List<String>) null);

    final String pluginClass = pluginProps.getString("alerter.class");
    //alerter.class是必须要配置的
    if (pluginClass == null) {
      logger.error("Alerter class is not set.");
      continue;
    } else {
      logger.info("Plugin class " + pluginClass);
    }
//加载所有的plugin类
    Class<?> alerterClass =
        PluginUtils.getPluginClass(pluginClass, pluginDir, extLibClassPaths, parentLoader);

    if (alerterClass == null) {
      continue;
    }
//获取类的.class路径
    final String source = FileIOUtils.getSourcePathFromClass(alerterClass);
    logger.info("Source jar " + source);
    jarPaths.add("jar:file:" + source);

    Constructor<?> constructor = null;
    try {
      constructor = alerterClass.getConstructor(Props.class);
    } catch (final NoSuchMethodException e) {
      logger.error("Constructor not found in " + pluginClass);
      continue;
    }
//反射方法获取插件对象
    Object obj = null;
    try {
      obj = constructor.newInstance(pluginProps);
    } catch (final Exception e) {
      logger.error(e);
    }

    if (!(obj instanceof Alerter)) {
      logger.error("The object is not an Alerter");
      continue;
    }

    final Alerter plugin = (Alerter) obj;
    installedAlerterPlugins.put(pluginName, plugin);
  }
//将所有插件类型以及所属对象放入Map中返回
  return installedAlerterPlugins;
}
  /**
   * Get URLClassLoader
   */
  public static URLClassLoader getURLClassLoader(final File pluginDir,
      List<String> extLibClassPaths,
      ClassLoader parentLoader) {
    final File libDir = new File(pluginDir, LIBRARY_FOLDER_NAME);
    if (libDir.exists() && libDir.isDirectory()) {
      final File[] files = libDir.listFiles();
      final ArrayList<URL> urls = getUrls(files);

      if (extLibClassPaths != null) {
        for (final String extLibClassPath : extLibClassPaths) {
          try {
            final File extLibFile = new File(pluginDir, extLibClassPath);
            if (extLibFile.exists()) {
              if (extLibFile.isDirectory()) {
                // extLibFile is a directory; load all the files in the
                // directory.
                final File[] extLibFiles = extLibFile.listFiles();
                urls.addAll(getUrls(extLibFiles));
              } else {
                final URL url = extLibFile.toURI().toURL();
                urls.add(url);
              }
            } else {
              logger.error(
                  "External library path not found. path = " + extLibFile.getAbsolutePath()
              );
              continue;
            }
          } catch (final MalformedURLException e) {
            logger.error(
                "Invalid External library path. path = " + extLibClassPath + " dir = " + pluginDir,
                e
            );
          }
        }
      }
      return new URLClassLoader(urls.toArray(new URL[urls.size()]), parentLoader);
    } else {
      logger.error("Library path not found. path = " + libDir);
      return null;
    }
  }
上一篇:Azkaban2.5.0部署安装(含安装包)


下一篇:Hadoop学习笔记(23)Azkaban的简介以及安装部署