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

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

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

相关系列博文:

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或者有更好的建议,欢迎批评指正,不吝感激

3. 扫描关注

小灰灰Blog&公众号

知识星球

180807-Quick-Task 动态脚本支持框架之Groovy脚本加载执行的更多相关文章

  1. 180723-Quick-Task 动态脚本支持框架之结构设计篇

    文章链接:https://liuyueyi.github.io/hexblog/2018/07/23/180723-Quick-Task-动态脚本支持框架之结构设计篇/ Quick-Task 动态脚本 ...

  2. 180719-Quick-Task 动态脚本支持框架之使用介绍篇

    文章链接:https://liuyueyi.github.io/hexblog/2018/07/19/180719-Quick-Task-动态脚本支持框架之使用介绍篇/ Quick-Task 动态脚本 ...

  3. 180729-Quick-Task 动态脚本支持框架之任务动态加载

    Quick-Task 动态脚本支持框架之任务动态加载 前面几篇博文分别介绍了整个项目的基本架构,使用说明,以及整体框架的设计与实现初稿,接下来则进入更细节的实现篇,将整个工程中核心实现捞出来,从为什么 ...

  4. JS脚本文件的位置对页面加载性能影响以及无阻塞脚本(javascript)模式

    JS的阻塞特性:当<script>出现的时候,页面必须等待脚本文件的加载.解析.执行完毕后才能继续进行页面的渲染.不管脚本文件是以内联形式还是外部引入的形式出现在<script> ...

  5. 001_Chrome 76支持原生HTML 图片懒加载Lazy loading

    Table Of Content 什么是懒加载? 语法参数及使用方式? 有哪些特点? 与js有关的实践 什么是懒加载? 技术背景 Web应用需要经常向后台服务器请求资源(通过查询数据库,是非常耗时耗资 ...

  6. Yaf框架下类的自动加载

    前面两篇博客分别讲述了PHP自带的类加载和composer中类的自动加载,其实Yaf框架也实现了基于PSR0和PSR4的类的自动加载.根据我对Yaf下类的自动加载方式的理解写下这篇博客.由于接触Yaf ...

  7. layui树形表格支持非异步和异步加载

    layui树形表格支持非异步和异步加载. 仓库地址:https://gitee.com/uniqid/ 使用示例如下: <div class="uui-admin-common-bod ...

  8. flask模板应用-加载静态文件:添加Favicon,使用CSS框架,使用宏加载静态资源

    加载静态文件 一个Web项目不仅需要HTML模板,还需要许多静态文件,比如CSS.JavaScript文件.图片和声音声.在flask程序中,默认需要将静态文件存储在与主脚本(包含程序实例的脚本)同级 ...

  9. Android批量图片加载经典系列——使用xutil框架缓存、异步加载网络图片

    一.问题描述 为提高图片加载的效率,需要对图片的采用缓存和异步加载策略,编码相对比较复杂,实际上有一些优秀的框架提供了解决方案,比如近期在git上比较活跃的xutil框架 Xutil框架提供了四大模块 ...

随机推荐

  1. Keepalived 实现双机热备

    原理 首先有一个虚拟ip暴露给客户端,虚拟ip对应的mac地址为一台真实服务器, 即用户向虚拟ip发送一个请求,该请求会被分发到真实服务器上. 现在有2台真实服务器,一台master,一台backup ...

  2. ORA-28001: the password has expired (DBD ERROR: OCISessionBegin)解决办法

    1.问题描述: 打开oracle在线管理页面发现这个错误:界面如下 2问题原因 造成这个问题的主要原因是因为DBSNMP .SYSMAN用户密码已经过期. 3解决办法 可以使用sys以管理员的身份登录 ...

  3. Java基础知识强化之集合框架笔记79:HashMap的实现原理

    1. HashMap的实现原理之 HashMap数据结构: HashMap是对数据结构中哈希表(Hash Table)的实现, Hash表又叫散列表.Hash表是根据关键码Key来访问其对应的值Val ...

  4. 用php代码统计数据库中符合条件的行数

    $sql1 = "select count(*) from t_user where age<17"; $data1 = mysql_query($sql1); $rows1 ...

  5. 4027. [HEOI2015]兔子与樱花【树形DP】

    Description 很久很久之前,森林里住着一群兔子.有一天,兔子们突然决定要去看樱花.兔子们所在森林里的樱花树很特殊.樱花树由n个树枝分叉点组成,编号从0到n-1,这n个分叉点由n-1个树枝连接 ...

  6. 20145203盖泽双 《Java程序设计》第8周学习总结

    20145203盖泽双 <Java程序设计>第8周学习总结 教材学习内容总结 1.java.util.logging包提供了日志功能相关类与接口,使用日志的起点是logger类,Logge ...

  7. head头的设计:rfcn light-head rfcn

    faster缺点:1.不是全卷积,roi出来后是两个fc层,这样会丧失平移变性.   2.每个roi都要单独经过两个fc层,也就是分别进行分类和回归,耗时 也有种说法是roi-pooling后导致平移 ...

  8. Python基础-画图:matplotlib.pyplot.scatter

    转载自博客:https://blog.csdn.net/qiu931110/article/details/68130199 matplotlib.pyplot.scatter 1.scatter函数 ...

  9. 使用.Net Core MVC创建Web API

    创建.Net Core MVC 打开appsettings.json文件,添加数据库连接 { "Logging": { "LogLevel": { " ...

  10. P1120 小木棍 [数据加强版]

    题目描述 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度. 给出每段小木棍的长度,编 ...