Groovy动态加载Java代码的使用方法和工具类

这篇具有很好参考价值的文章主要介绍了Groovy动态加载Java代码的使用方法和工具类。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、使用场景

你是否遇到过:线上环境复杂,发包申请复杂,代码稳健性差,或者某段代码需要视线上运行情况而更改的!又或者类似解析脚本经常变动,通配符优化等等!更新、打包、发布申请、然后再发布…
Groovy则提供了相关的动态加载能力来解决这些问题,并且简单易懂,非常好用!

二、Groovy优缺点

缺点

  1. 使用Groovy会增加一定的代码复杂度,因为你原本只用写业务代码就行,但现在你不但要写业务代码,还要增加Groovy的代码。
  2. Groovy有两种方式,一种是使用他自己的Groovy语言来进行处理,这要求学习Groovy。另一种则是使用Groovy提供的java版本工具包,使用Java语言处理,这个方法没有新的学习成本,但是要求写的非常详细,例如引入一个对象,则需要把对应的import也写出来,否则就会报错。
  3. 考虑动态代码的异常处理。

优点

  1. 动态加载代码,避免重复劳动,可以放在文件里,或者配置到界面上,真的很方便!!!
  2. 有Java版本的Groovy工具,可以直接使用Java代码,不用学习新的语言。
  3. 首次加载新的代码会慢一些,但是后面和正常代码速度差不多(个人测试感觉)。

三、工具类

网上有很多Java的Groovy的工具的使用方法讲的比较清楚,我项目中因为很多地方会使用到,所以就顺手写了个工具类,有需要的可以复制使用。

首先引入POM:

        <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy</artifactId>
            <version>3.0.9</version>
        </dependency>

然后复制粘贴:

import groovy.lang.GroovyClassLoader;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class GroovyHandler {

    private Class<?> clazz;
    private Object instance;
    private Method method;
    private Constructor<?> constructor;

	//加载String类型的代码
    public GroovyHandler(String javasShell) {
        this.clazz = new GroovyClassLoader().parseClass(javasShell);
    }
    //加载文件类型的代码
    public GroovyHandler(File file) {
        try {
            this.clazz = new GroovyClassLoader().parseClass(file);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
	//设置构造函数(如果代码里带有Class)
    public void setConstructor(Class<?>... parameterTypes) {
        try {
            this.constructor = this.clazz.getConstructor(parameterTypes);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
	//设置构造函数的参数并生成实例对象
    public void setInstance(Object... constructorValue) {
        try {
            if(this.constructor == null){
                this.instance = this.clazz.newInstance();
            }else {
                this.instance = this.constructor.newInstance(constructorValue);
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
	//设置要调用方法(如果有参数,带上参数类型)
    public void setMethod(String methodName, Class<?>... parameterTypes) {
        try {
            this.method = this.clazz.getDeclaredMethod(methodName, parameterTypes);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
	//调用方法(如果有参数,带上参数值)
    public Object doInvoke(Object... args) {
        try {
            return this.method.invoke(this.instance, args);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }


}

四、使用示例

//示例代码:
//1.如果需要直接调用某个方法,没有构造函数:
//脚本例如下面:
//    public String getBuilder(String name){
//        return name + ":builder";
//    }
public static void main(String[] args) {
        String scirpt = "public String getBuilder(String name){\n" +
                "        return name + \":builder\";\n" +
                "    }";
        //加载字符串
        GroovyHandler groovyHandler = new GroovyHandler(scirpt);
        //加载文件
        //GroovyHandler groovyHandler = new GroovyHandler(file);
        //直接生成类的实例对象
        groovyHandler.setInstance();
        //设置需要调用的方法并传参数的类型(如果没有参数则不写)
        groovyHandler.setMethod("getBuilder",String.class);
        //反射调用方法并传参(如果没有参数则不写,传回的值可以进行强转)
        String result = (String) groovyHandler.doInvoke("zhangsan");
        System.out.println(result);
    }
//输出结果:zhangsn:builder

//2.有构造函数
//脚本代码例如下面的:
//public class TestGroovy {
//    private String age;
//
//    public TestGroovy(String age) {
//        this.age = age;
//    }
//
//    public String getNewStr(String name) {
//        return name + ":" + age;
//    }
//}
 public static void main(String[] args) {
        String script = "public class TestGroovy {\n" +
                "    private String age;\n" +
                "\n" +
                "    public TestGroovy(String age) {\n" +
                "        this.age = age;\n" +
                "    }\n" +
                "\n" +
                "    public String getNewStr(String name) {\n" +
                "        return name + \":\" + age;\n" +
                "    }\n" +
                "}";

        //加载String
        GroovyHandler groovyHandler = new GroovyHandler(script);
        //加载文件
        //GroovyHandler groovyHandler = new GroovyHandler(file);
        if (groovyHandler != null) {
            //如果代码脚本里面有构造函数需要调用,先调用第一句,参数填写构造的参数类型!
            groovyHandler.setConstructor(String.class);
            //然后传入上面构造函数需要的参数,groovy会自动生成实例对象
            groovyHandler.setInstance("18");
            //设置需要调用的方法并传参数的类型(如果没有参数则不写)
            groovyHandler.setMethod("getNewStr",String.class);
            //反射调用方法并传参(如果没有参数则不写,传回的值可以进行强转)
            String result = (String)groovyHandler.doInvoke("zhangsan");
            System.out.println(result);
        }
    }
//输出结果:zhangsan:18

需要注意的是Groovy加载的代码里,必须要包含对应对象的引用,传对象参数时,则需要将对象的Import地址添加上,否则Groovy找不到对应的类,会报Null错误!!!文章来源地址https://www.toymoban.com/news/detail-689239.html

总结:Groovy可以动态加载代码,在某些应用场景下还是很方便的!但是需要代码需要写的完善一些,并且做好异常处理。如果有问题可以问我,或者有错误指点请弹我,祝永无Bug!

到了这里,关于Groovy动态加载Java代码的使用方法和工具类的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Py:代码性能分析之使用python工具—如利用cProfile【输出每个函数的运行时间和调用次数】/line_profiler【输出每行代码的执行时间】)同时对比斐波那契数列问题的递归方法和动态规划

    Py:代码性能分析之使用python工具—如利用cProfile【输出每个函数的运行时间和调用次数】/line_profiler【输出每行代码的执行时间】)同时对比斐波那契数列问题的递归方法和动态规划算法实现 目录

    2024年02月04日
    浏览(79)
  • 【QCustomPlot】使用方法(动态库方式)

    使用 QCustomPlot 绘图库辅助开发时整理的学习笔记。同系列文章目录可见 《绘图库 QCustomPlot 学习笔记》目录。本篇介绍 QCustomPlot 的一种使用方法,通过动态库的方式进行使用,示例中使用的 QCustomPlot 版本为 Version 2.1.1 。 目录 说明 1. 下载源码 2. 编译动态库 2.1 编译动态库的

    2024年02月09日
    浏览(38)
  • 使用LOAD DATA INFILE命令加载数据文件到MySQL数据库的方法和常见错误及解决方法

    【免责声明】文章仅供学习交流,观点代表个人,与任何公司无关。 编辑|SQL和数据库技术(ID:SQLplusDB) 在MySQL数据库中,可以使用LOAD DATA INFILE命令将数据从 CSV 文件导入已创建的表中。 LOAD DATA INFILE的语法详细如下: 参考: 3.3.3 Loading Data into a Table https://dev.mysql.com/doc/refman/8.

    2024年02月09日
    浏览(37)
  • Hive动态分区和分桶使用场景和使用方法

            按照数据表的某列或某些列分为多个分区,分区从形式上可以理解为文件夹,比如我们要收集某个大型 网站的日志数据,一个网站每天的日志数据存在同一张表上,由于每天会生成大量的日志,导致数据表 的内容巨大,在查询时进行全表扫描耗费的资源非常多。那

    2024年02月04日
    浏览(49)
  • 【MySQL】使用LOAD DATA INFILE命令加载数据文件到MySQL数据库的方法和常见错误及解决方法

    【免责声明】文章仅供学习交流,观点代表个人,与任何公司无关。 编辑|SQL和数据库技术(ID:SQLplusDB) 在MySQL数据库中,可以使用LOAD DATA INFILE命令将数据从 CSV 文件导入已创建的表中。 LOAD DATA INFILE的语法详细如下: 参考: 3.3.3 Loading Data into a Table https://dev.mysql.com/doc/refman/8.

    2024年02月09日
    浏览(45)
  • Vue 3使用 Iconify 作为图标库与图标离线加载的方法、 Icones 开源在线图标浏览库的使用

    之前一直naive-ui搭配使用的是xicons,后来发现Iconify支持的图标合集更多,因此转而使用Iconify。 与FontAwesome不同的是,Iconify配合Icones相当于是一个合集,Iconify提供了快捷引入图标的方式,而Icones是一个大的图标库,收集了大量MIT协议、Apache 2.0开源的图标文件。 Iconify 支持的框

    2024年02月08日
    浏览(42)
  • SwiftUI 中List动态列表容器视图的使用方法

    List  是 SwiftUI 中用于显示动态列表的容器视图。它接受一个或多个子视图,并根据提供的数据动态生成对应的列表项。 下面是  List  的常见用法和一些常用的参数: 基本用法: 在这个例子中, List  包含了三个  Text  视图作为列表项。 使用  ForEach  进行动态列表生成:  

    2024年02月07日
    浏览(54)
  • 设计模式的使用——模板方法模式+动态代理模式

    一、需求介绍   现有自己写的的一套审批流程逻辑,由于代码重构,需要把以前的很多业务加上审批的功能,再执行完审批与原有业务之后,生成一个任务,然后再统一处理一个任务(本来是通过数据库作业去处理的,后来说这个任务要马上去处理,只能去统一添加一个处

    2024年02月10日
    浏览(35)
  • iPhone 14 Pro 动态岛的功能和使用方法详解

    当iPhone 14 Pro机型发布时,苹果公司将软件功能与屏幕顶部的药丸状切口创新集成,称之为“灵动岛”,这让许多人感到惊讶。这篇文章解释了它的功能、工作原理,以及你如何与它互动以执行动作。 在谣言周期的早期‌iPhone 14 Pro‌ 在宣布时,我们了解到苹果公司正在开发一

    2024年02月11日
    浏览(52)
  • Netplan使用(高版本Ubuntu静态/动态IP设置方法)

    NetworkManager and netplan Ubuntu 18.04开始,Ubuntu和Debian移除了以前的 ifup/ifdown 命令和/etc/network/interfaces配置文件,转而使用 ip link set 或者 /etc/netplan/01-netcfg.yaml 模板和 sudo netplan apply 命令实现网络管理。 Netplan 是抽象网络配置描述器,用于配置 Linux 网络。 通过 netplan 命令,你只需用

    2024年01月16日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包