Java工具箱-动态编译Janino

1,157 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情

Janino官网

Janino是一个轻量级的Java编译器。作为Library,它可以直接在Java程序中调用,动态编译java代码并加载。 编译时可以直接引用JVM中已经加载的类.

支持绝大部分java语法,官方网站上有详细各个版本支持的语法.依据官方的说法简单表达式编译甚至比jdk更快。

官网上的例子及介绍十分详细,有兴趣的同学可以直接查看官网。

增加pom依赖

<dependency>
    <groupId>org.codehaus.janino</groupId>
    <artifactId>janino</artifactId>
    <version>3.0.7</version>
</dependency>

基础用法

简单表达式执行示例

import org.codehaus.janino.*;
public class JaninoDemo {

    public static void main(String[] args) throws InvocationTargetException, CompileException {
        ExpressionEvaluator ee = new ExpressionEvaluator();
        ee.setParameters(new String[]{"param"}, new Class[]{Param.class});
        ee.setExpressionType(String.class);
        ee.cook("param.getA() + param.getB()");
        Param param = new Param();
        param.setA("a");
        param.setB("B");
        String resultStr = (String) ee.evaluate(new Param[]{param});
        System.out.println(resultStr);
    }
}
//参数实体
public class Param{
    private String a;
    private String b;

    public String getA() {
        return a;
    }

    public void setA(String a) {
        this.a = a;
    }

    public String getB() {
        return b;
    }

    public void setB(String b) {
        this.b = b;
    }
}

输出结果

Connected to the target VM, address: '127.0.0.1:3797', transport: 'socket'
aB

关键代码说明

  • ee.setParameters:设置入参类型
  • ee.setExpressionType:设置返回值类型
  • ee.cook:设置需处理的表达式,支持多种格式String/File/InputStream……
  • ee.evaluate:执行表达式并获取结果

参数所对应的JavaBean需具备get/set方法,不支持lombok相关注解。

代码段执行示例:


public class JaninoDemo {

    public static void main(String[] args) throws InvocationTargetException, CompileException {
        scriptEvaluator();
    }

    public static void expressionEvaluator() {
        try {
            ExpressionEvaluator ee = new ExpressionEvaluator();
            ee.setParameters(new String[]{"a", "b"}, new Class[]{int.class, int.class});
            ee.setExpressionType(int.class);
            ee.cook("a + b");
            int result = (Integer) ee.evaluate(new Integer[]{8, 9});
            System.out.println(result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void scriptEvaluator() throws CompileException, InvocationTargetException {
        ScriptEvaluator se = new ScriptEvaluator();
        se.cook("import static com.meijm.toolbox.janino.JaninoDemo.*;" +
                "expressionEvaluator();");
        se.setDebuggingInformation(true, true, true);
        se.evaluate(null);
    }

}

注意事项

  • cook中的代码块支持常见java语法。
  • se.setDebuggingInformation:设置调试开关,打开后脚本对应的方法支持调试
  • 脚本中调用的静态方法expressionEvaluator() 不能抛出异常,需自己处理异常信息。

参考资料

janino-compiler.github.io/janino/

github.com/janino-comp…