为了账号安全,请及时绑定邮箱和手机立即绑定

Datax3.0插件加载流程

标签:
Java
我们知道Datax是基于框架+插件方式进行开发的。
之前我们也了解了怎么开发一个简单的插件。那这些插件是怎么被加载和使用的?

源码查看

  • com.alibaba.datax.core.job.JobContainer
进入start()方法的this.init()方法
进入this.jobReader = this.initJobReader(jobPluginCollector);
private Reader.Job initJobReader(
            JobPluginCollector jobPluginCollector) {
        this.readerPluginName = this.configuration.getString(
                CoreConstant.DATAX_JOB_CONTENT_READER_NAME);//job.content[0].reader.name  获取插件的名称
        classLoaderSwapper.setCurrentThreadClassLoader(LoadUtil.getJarLoader(
                PluginType.READER, this.readerPluginName));

        Reader.Job jobReader = (Reader.Job) LoadUtil.loadJobPlugin(
                PluginType.READER, this.readerPluginName);

        // 设置reader的jobConfig
        jobReader.setPluginJobConf(this.configuration.getConfiguration(
                CoreConstant.DATAX_JOB_CONTENT_READER_PARAMETER));

        // 设置reader的readerConfig
        jobReader.setPeerPluginJobConf(this.configuration.getConfiguration(
                CoreConstant.DATAX_JOB_CONTENT_WRITER_PARAMETER));

        jobReader.setJobPluginCollector(jobPluginCollector);
        jobReader.init();

        classLoaderSwapper.restoreCurrentThreadClassLoader();
        return jobReader;
}
上面代码主要做了:
通过配置文件获取插件的名称
保存当前classLoader,并将当前线程的classLoader设置为所给classLoader
加载Reader 插件的实现类
初始化Reader的参数
执行Reader  job的init方法
将当前线程的类加载器设置为保存的类加载,恢复
  • 加载插件方法
 public static AbstractJobPlugin loadJobPlugin(PluginType pluginType,
                                                  String pluginName) {
        Class<? extends AbstractPlugin> clazz = LoadUtil.loadPluginClass(
                pluginType, pluginName, ContainerType.Job);

        try {
            AbstractJobPlugin jobPlugin = (AbstractJobPlugin) clazz
                    .newInstance();
            jobPlugin.setPluginConf(getPluginConf(pluginType, pluginName));
            return jobPlugin;
        } catch (Exception e) {
            throw DataXException.asDataXException(
                    FrameworkErrorCode.RUNTIME_ERROR,
                    String.format("DataX找到plugin[%s]的Job配置.",
                            pluginName), e);
        }
    }	
通过LoadUtil.loadPluginClass(
                pluginType, pluginName, ContainerType.Job) 方法加载到我们需要的class,然后通过反射进行实例化。
  • 加载Class的方法
 private static synchronized Class<? extends AbstractPlugin> loadPluginClass(
            PluginType pluginType, String pluginName,
            ContainerType pluginRunType) {
        Configuration pluginConf = getPluginConf(pluginType, pluginName);
        JarLoader jarLoader = LoadUtil.getJarLoader(pluginType, pluginName);
        try {
            return (Class<? extends AbstractPlugin>) jarLoader
                    .loadClass(pluginConf.getString("class") + "$"
                            + pluginRunType.value());
        } catch (Exception e) {
            throw DataXException.asDataXException(FrameworkErrorCode.RUNTIME_ERROR, e);
        }
    }
这里获取到JarLoader(继承子URLClassLoader)
通过JarLoader的loadClass方法加载我们plugin.json配置的class
  • 获取ClassLoader方法 getJarLoader
public static synchronized JarLoader getJarLoader(PluginType pluginType,
                                                      String pluginName) {
        Configuration pluginConf = getPluginConf(pluginType, pluginName);

        JarLoader jarLoader = jarLoaderCenter.get(generatePluginKey(pluginType,
                pluginName));
        if (null == jarLoader) {
            String pluginPath = pluginConf.getString("path");
            if (StringUtils.isBlank(pluginPath)) {
                throw DataXException.asDataXException(
                        FrameworkErrorCode.RUNTIME_ERROR,
                        String.format(
                                "%s插件[%s]路径非法!",
                                pluginType, pluginName));
            }
            jarLoader = new JarLoader(new String[]{pluginPath});
            jarLoaderCenter.put(generatePluginKey(pluginType, pluginName),
                    jarLoader);
        }

        return jarLoader;
    }
此方法流程:
根据类型和名称从缓存中获取
如果没有则去创建,首先获取插件的路径.比如:"path": "D:\\app\\workspace\\idea\\DataX\\target\\datax\\datax\\plugin\\reader\\mysqlreader"
然后根据JarLoader里面的getURLs(paths)获取插件路径下所有的jar包。
创建单独的URLClassLoader。
把创建的ClassLoader缓存起来,后续就不用重新创建ClassLoader,返回。
  • com.alibaba.datax.core.util.container.JarLoader
com.alibaba.datax.core.util.container.JarLoader
此类:提供Jar隔离的加载机制,会把传入的路径、及其子路径、以及路径中的jar文件加入到class path
这里就不展示代码了。
reader job加载完之后,reader task
writer job ,writer task都是一样的流程,快去查看一下吧。
点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
6396
获赞与收藏
157

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消