专栏首页小灰灰180807-Quick-Task 动态脚本支持框架之Groovy脚本加载执行

180807-Quick-Task 动态脚本支持框架之Groovy脚本加载执行

Quick-Task 动态脚本支持框架之Groovy脚本加载执行

上一篇简答说了如何判断有任务动态添加、删除或更新,归于一点就是监听文件的变化,判断目录下的Groovy文件是否有新增删除和改变,从而判定是否有任务的变更;

接下来的问题就比较明显了,当任务变更之后,就需要重新加载任务了,即如何动态的编译并执行Groovy文件呢?

相关系列博文:

<!--more-->

I. Groovy文件动态加载

要想动态加载类,可以怎么办?如果对JVM有一定了解的朋友可能知道,自定义一个ClassLoader,可以实现从文件/网络/DB/Jar包中读取class文件,而Groovy,动态语言,简单来说就是.groovy文件可以直接运行,那么我们编码中要怎么玩?

1. 依赖

让我自己来实现Groovy文件的编译执行,目前基本上是看不到啥希望的,所以果断的借助第三方工具类加载Groovy文件

pom文件添加依赖

<dependency>
    <groupId>org.codehaus.groovy</groupId>
    <artifactId>groovy-all</artifactId>
    <version>2.4.3</version>
</dependency>

2. 加载Groovy

直接利用上面jar包中提供的GroovyCalssLoader来加载Groovy文件即可,使用也比较简单

@Slf4j
public class GroovyCompile {

    @SuppressWarnings("unchecked")
    public static <T> T compile(File codeSource, Class<T> interfaceType, ClassLoader classLoader)
            throws CompileTaskScriptException {
        try {
            GroovyClassLoader loader = new GroovyClassLoader(classLoader);
            Class clz = loader.parseClass(codeSource);

            // 接口校验
            if (!interfaceType.isAssignableFrom(clz)) {
                throw new CompileTaskScriptException("illegal script type!");
            }

            return (T) clz.newInstance();
        } catch (IOException e) {
            log.error("load code from {} error! e: {}", codeSource, e);
            throw new CompileTaskScriptException("load code from " + codeSource + " error!");
        } catch (CompileTaskScriptException e) {
            throw e;
        } catch (Exception e) {
            log.error("initial script error! codePath: {}, e: {}", codeSource, e);
            throw new CompileTaskScriptException(
                    "initial script error! clz: " + codeSource + " msg: " + e.getMessage());
        }
    }
}

上面看着挺多,关键地方就三行,编译为class对象之后,借助反射来创建对象

GroovyClassLoader loader = new GroovyClassLoader(classLoader);
Class clz = loader.parseClass(codeSource);
return (T) clz.newInstance();

另外还有一行,也可以顺带凑一眼,判断一个class是否为另一个class的子类,用的是

interfaceType.isAssignableFrom(clz)

而判断某个对象是否为某类的子类用的则是 instance of

3. 调用包装

上面既然提供了一个工具类,那么接上篇的获取变动文件之后,获取File对象,借此拿到任务对象,就比较清晰了

@Slf4j
public class ScriptLoadUtil {

    public static ITask loadScript(File file) {
        try {
            return GroovyCompile.compile(file, ITask.class, ScriptLoadUtil.class.getClassLoader());
        } catch (CompileTaskScriptException e) {
            log.error("un-expect error! e: {}", e);
            return null;
        }
    }
}

4. 小结

本篇内容比较简单,知识点也没多少,一个是利用GroovyClassLoader来编译Groovy文件并获取实例;另一个就是如何判断一个class是否为另一个class的子类

还有一个隐藏的点上面没有说,那就是上面的GroovyCompile文件中,每次加载Groovy文件时,都是新创建了一个GroovyClassLoader,并由它来加载并实例Groovy任务,那么问题来了

  • 能否用一个GoorvyClassLoader来管理所有的Groovy任务呢?
  • 上面的代码实现中,不同的Groovy任务之间,可以相互通信么?

针对上面的问题,暂不给出答案,后面再说

II. 其他

0. 相关

博文:

项目:

1. 一灰灰Bloghttps://liuyueyi.github.io/hexblog

一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛

2. 声明

尽信书则不如,已上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Quick-Task 动态脚本支持框架之Groovy脚本加载执行

    上一篇简答说了如何判断有任务动态添加、删除或更新,归于一点就是监听文件的变化,判断目录下的Groovy文件是否有新增删除和改变,从而判定是否有任务的变更;

    一灰灰blog
  • 【SpringBoot MQ 系列】RabbitListener 消费基本使用姿势介绍

    之前介绍了 rabbitmq 的消息发送姿势,既然有发送,当然就得有消费者,在 SpringBoot 环境下,消费可以说比较简单了,借助@RabbitListe...

    一灰灰blog
  • SpringBoot系列教程web篇之Beetl环境搭建

    前面两篇分别介绍了目前流行的模板引擎Freemaker和Thymeleaf构建web应用的方式,接下来我们看一下号称性能最好的国产模板引擎Beetl,如何搭建w...

    一灰灰blog
  • 【每日一题】问题 1238: 演讲大赛评分

    最近"老王"很开心.他在大一的时候参加过数计学院的“软件小组”。告诉你个秘密,这个小组是个好地方,不但活动精彩而且有MM。 这不,这个小组举办了一个叫做“计算...

    编程范 源代码公司
  • 在对 Angular 的文档 aio 进行编译的时候提示错误

    请需要根据提示使用 Yarn 1.13 版本就可以了。我们在 aio 文档进行编译的时候,发现如果 yarn 的版本过高的话是没有办法编译成功的,因此请不要按照...

    HoneyMoose
  • ​图;代码轻松理解,代理

    代理 代理是英文 Proxy 翻译过来的。我们在生活中见到过的代理,大概最常见的就是朋友圈中卖面膜的同学了。 她们从厂家拿货,然后在朋友圈中宣传,然后卖给熟人。...

    Java帮帮
  • JavaScript 设计模式学习第十一篇-代理模式

    代理模式(Proxy Pattern)又称委托模式,它为目标对象创造了一个代理对象,以控制对目标对象的访问。

    越陌度阡
  • Android开发笔记(一百六十七)Android8.0的画中画模式

    前面的博文《Android开发笔记(一百五十九)Android7.0的分屏模式》介绍了Android7.0的多窗口特性,但是这...

    用户4464237
  • 浅谈FPGA与音频处理器的结合

    FPGA通常是面向通信行业,尽管其主要开发者仍然专注于通信应用, 但他们越来越关注存储和服务器市场。

    半吊子全栈工匠
  • 使用深度语义散列的基于检索聊天机器人中超快速,低存储,高效的粗粒度选择

    使用深度语义散列的基于检索聊天机器人中超快速,低存储,高效的粗粒度选择(computer science)

    用户8054058

扫码关注云+社区

领取腾讯云代金券