前言:
项目中引用了这个库,主要是在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();
}
}
}
2、http://janino.unkrig.de/samples/ScriptDemo.java
————————————————
版权声明:本文为CSDN博主「inrgihc」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/inrgihc/article/details/104399439/