当前位置: 首页 > 工具软件 > Janino > 使用案例 >

Janino框架初识与使用教程

陆高峰
2023-12-01

前言:

项目中引用了这个库,主要是在logback中使用到。

一、 Janino简介
        Janino 是一个极小、极快的 开源Java 编译器(Janino is a super-small, super-fast Java™ compiler.)。Janino 不仅可以像 JAVAC 一样将 Java 源码文件编译为字节码文件,还可以编译内存中的 Java 表达式、块、类和源码文件,加载字节码并在 JVM 中直接执行。Janino 同样可以用于静态代码分析和代码操作。

项目地址:https://github.com/janino-compiler/janino

官网地址:http://janino-compiler.github.io/janino/

二、Janino的应用
1、Kettle使用Janino框架来实现自定义"Java代码组件"步骤功能;

详细介绍地址:http://www.uml.org.cn/sjjmck/201910101.asp?artid=22506

2、在日志框架里当引用 slf4j + log4j/logback 的时候,常常会顺带引用 Janino 来提高日志输出的性能

详细介绍地址:http://logback.qos.ch/manual/configuration.html#conditional

三、使用教程
在使用前需要在pom.xml中引入如下依赖:

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

 
注:请查看官网最新版本发布情况;

1、打印最简单的Hello World!

import org.codehaus.commons.compiler.IScriptEvaluator;
import org.codehaus.janino.ScriptEvaluator;
 
public class JaninoTester01 {
 
    public static void main(String[] args) {
        try {
            String content="System.out.println(\"Hello world\");";
            IScriptEvaluator evaluator = new ScriptEvaluator();
            evaluator.cook(content);
            evaluator.evaluate(null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
}


2、执行最简单的算数表达式计算

import org.codehaus.janino.ExpressionEvaluator;
import org.codehaus.janino.ScriptEvaluator;
 
public class JaninoTester02 {
 
    public static void main(String[] args) {
        try {
            String express = "(1+2)*3";
            ScriptEvaluator evaluator = new ExpressionEvaluator();
            evaluator.cook(express);
            Object res = evaluator.evaluate(null);
            System.out.println(express + "=" + res);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
}


3、执行带参数的表达式计算

import java.lang.reflect.InvocationTargetException;
import org.codehaus.commons.compiler.CompileException;
import org.codehaus.janino.ExpressionEvaluator;
 
public class JaninoTester03 {
 
    public static void main(String[] args) throws CompileException, InvocationTargetException {
        // 首先定义一个表达式模拟器ExpressionEvaluator对象
        ExpressionEvaluator ee = new ExpressionEvaluator();
 
        // 定义一个算术表达式,表达式中需要有2个int类型的参数a和b
        String expression = "2 * (a + b)";
        ee.setParameters(new String[] { "a", "b" }, new Class[] { int.class, int.class });
 
        // 设置表达式的返回结果也为int类型
        ee.setExpressionType(int.class);
 
        // 这里处理(扫描,解析,编译和加载)上面定义的算数表达式.
        ee.cook(expression);
 
        // 根据输入的a和b参数执行实际的表达式计算过程
        int result = (Integer) ee.evaluate(new Object[] { 19, 23 });
        System.out.println(expression + " = " + result);
    }
 
}


4、执行java脚本中的函数

import java.lang.reflect.InvocationTargetException;
import org.codehaus.commons.compiler.CompileException;
import org.codehaus.janino.ScriptEvaluator;
 
public class JaninoTester04 {
 
    public static void main(String[] args) throws CompileException, InvocationTargetException {
        ScriptEvaluator se = new ScriptEvaluator();
        se.cook(
            ""
            + "static void method1() {\n"
            + "    System.out.println(\"run in method1()\");\n"
            + "}\n"
            + "\n"
            + "static void method2() {\n"
            + "    System.out.println(\"run in method2()\");\n"
            + "}\n"
            + "\n"
            + "method1();\n"
            + "method2();\n"
            + "\n"
 
        );
 
        se.evaluate(null);
    }
 
}

5、向java脚本中传递参数

import java.lang.reflect.InvocationTargetException;
import org.codehaus.commons.compiler.CompileException;
import org.codehaus.janino.ScriptEvaluator;
 
public class JaninoTester05 {
 
    public static void main(String[] args) throws CompileException, InvocationTargetException {
        ScriptEvaluator se = new ScriptEvaluator();
        se.setParameters(new String[] { "arg1", "arg2" }, new Class[] { String.class, int.class });
        se.cook(
            ""
            + "System.out.println(arg1);\n"
            + "System.out.println(arg2);\n"
            + "\n"
            + "static void method1() {\n"
            + "    System.out.println(\"run in method1()\");\n"
            + "}\n"
            + "\n"
            + "public static void method2() {\n"
            + "    System.out.println(\"run in method2()\");\n"
            + "}\n"
            + "\n"
            + "method1();\n"
            + "method2();\n"
            + "\n"
 
        );
        se.evaluate(new Object[]{"aaa",22});
    }
 
}


6、在Java脚本中实现一个接口以供直接调用

import java.io.StringReader;
import org.codehaus.janino.ClassBodyEvaluator;
import org.codehaus.janino.Scanner;
 
public class JaninoTester06 {
    
    public interface Foo {
        int bar(int a, int b);
    }
    
    public static void main(String[] args) throws Exception {
        Foo f = (Foo) ClassBodyEvaluator.createFastClassBodyEvaluator(
            new Scanner(null, new StringReader("public int bar(int a, int b) { return a + b; }")),
            Foo.class,                  // 实现的父类或接口
            (ClassLoader) null          // 这里设置为null表示使用当前线程的class loader
        );
        System.out.println("1 + 2 = " + f.bar(1, 2));
 
    }
 
}


7、在Java脚本中自定义类与调用
步骤(1):定义一个基类BaseClass

package com.tang.janino.obj;
 
public class BaseClass {
    
    private String baseId;
 
    public BaseClass(String baseId) {
        super();
        this.baseId = baseId;
    }
 
    @Override
    public String toString() {
        return "BaseClass [baseId=" + baseId + "]";
    }
 
}


步骤(2):定义一个子类DerivedClass

package com.tang.janino.obj;
 
public class DerivedClass extends BaseClass {
 
    private String name;
 
    public DerivedClass(String baseId, String name) {
        super(baseId);
        this.name = name;
    }
 
    @Override
    public String toString() {
        return super.toString() + "DerivedClass [name=" + name + "]";
    }
 
}


步骤(4):构造java脚本,调用上述类

import org.codehaus.commons.compiler.IScriptEvaluator;
import org.codehaus.janino.ScriptEvaluator;
 
public class JaninoTester07 {
 
    public static void main(String[] args) {
        try {
            IScriptEvaluator se = new ScriptEvaluator();
            se.setReturnType(String.class);
            se.cook("import com.tang.janino.obj.BaseClass;\n"
                    + "import com.tang.janino.obj.DerivedClass;\n"
                    + "BaseClass o=new DerivedClass(\"1\",\"join\");\n" 
                    + "return o.toString();\n");
            Object res = se.evaluate(new Object[0]);
            System.out.println(res);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
}


四、其他用法
1、https://www.programcreek.com/java-api-examples/index.php?api=org.codehaus.commons.compiler.IClassBodyEvaluator

2、http://janino.unkrig.de/samples/ScriptDemo.java​​​​​​​
————————————————
版权声明:本文为CSDN博主「inrgihc」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/inrgihc/article/details/104399439/

 类似资料: