Janino框架初识与使用教程

一、 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中引入如下依赖:

 
  1. <dependency>
  2. <groupId>org.codehaus.janino</groupId>
  3. <artifactId>janino</artifactId>
  4. <version>3.0.11</version>
  5. </dependency>
 

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

1、打印最简单的Hello World!

 
  1. import org.codehaus.commons.compiler.IScriptEvaluator;
  2. import org.codehaus.janino.ScriptEvaluator;
  3.  
  4. public class JaninoTester01 {
  5.  
  6. public static void main(String[] args) {
  7. try {
  8. String content="System.out.println(\"Hello world\");";
  9. IScriptEvaluator evaluator = new ScriptEvaluator();
  10. evaluator.cook(content);
  11. evaluator.evaluate(null);
  12. } catch (Exception e) {
  13. e.printStackTrace();
  14. }
  15. }
  16.  
  17. }
 

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

 
  1. import org.codehaus.janino.ExpressionEvaluator;
  2. import org.codehaus.janino.ScriptEvaluator;
  3.  
  4. public class JaninoTester02 {
  5.  
  6. public static void main(String[] args) {
  7. try {
  8. String express = "(1+2)*3";
  9. ScriptEvaluator evaluator = new ExpressionEvaluator();
  10. evaluator.cook(express);
  11. Object res = evaluator.evaluate(null);
  12. System.out.println(express + "=" + res);
  13. } catch (Exception e) {
  14. e.printStackTrace();
  15. }
  16. }
  17.  
  18. }
 

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

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

4、执行java脚本中的函数

 
  1. import java.lang.reflect.InvocationTargetException;
  2. import org.codehaus.commons.compiler.CompileException;
  3. import org.codehaus.janino.ScriptEvaluator;
  4.  
  5. public class JaninoTester04 {
  6.  
  7. public static void main(String[] args) throws CompileException, InvocationTargetException {
  8. ScriptEvaluator se = new ScriptEvaluator();
  9. se.cook(
  10. ""
  11. + "static void method1() {\n"
  12. + " System.out.println(\"run in method1()\");\n"
  13. + "}\n"
  14. + "\n"
  15. + "static void method2() {\n"
  16. + " System.out.println(\"run in method2()\");\n"
  17. + "}\n"
  18. + "\n"
  19. + "method1();\n"
  20. + "method2();\n"
  21. + "\n"
  22.  
  23. );
  24.  
  25. se.evaluate(null);
  26. }
  27.  
  28. }
 

5、向java脚本中传递参数

 
  1. import java.lang.reflect.InvocationTargetException;
  2. import org.codehaus.commons.compiler.CompileException;
  3. import org.codehaus.janino.ScriptEvaluator;
  4.  
  5. public class JaninoTester05 {
  6.  
  7. public static void main(String[] args) throws CompileException, InvocationTargetException {
  8. ScriptEvaluator se = new ScriptEvaluator();
  9. se.setParameters(new String[] { "arg1", "arg2" }, new Class[] { String.class, int.class });
  10. se.cook(
  11. ""
  12. + "System.out.println(arg1);\n"
  13. + "System.out.println(arg2);\n"
  14. + "\n"
  15. + "static void method1() {\n"
  16. + " System.out.println(\"run in method1()\");\n"
  17. + "}\n"
  18. + "\n"
  19. + "public static void method2() {\n"
  20. + " System.out.println(\"run in method2()\");\n"
  21. + "}\n"
  22. + "\n"
  23. + "method1();\n"
  24. + "method2();\n"
  25. + "\n"
  26.  
  27. );
  28. se.evaluate(new Object[]{"aaa",22});
  29. }
  30.  
  31. }
 

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

 
  1. import java.io.StringReader;
  2. import org.codehaus.janino.ClassBodyEvaluator;
  3. import org.codehaus.janino.Scanner;
  4.  
  5. public class JaninoTester06 {
  6.  
  7. public interface Foo {
  8. int bar(int a, int b);
  9. }
  10.  
  11. public static void main(String[] args) throws Exception {
  12. Foo f = (Foo) ClassBodyEvaluator.createFastClassBodyEvaluator(
  13. new Scanner(null, new StringReader("public int bar(int a, int b) { return a + b; }")),
  14. Foo.class, // 实现的父类或接口
  15. (ClassLoader) null // 这里设置为null表示使用当前线程的class loader
  16. );
  17. System.out.println("1 + 2 = " + f.bar(1, 2));
  18.  
  19. }
  20.  
  21. }
 

7、在Java脚本中自定义类与调用

步骤(1):定义一个基类BaseClass

 
  1. package com.tang.janino.obj;
  2.  
  3. public class BaseClass {
  4.  
  5. private String baseId;
  6.  
  7. public BaseClass(String baseId) {
  8. super();
  9. this.baseId = baseId;
  10. }
  11.  
  12. @Override
  13. public String toString() {
  14. return "BaseClass [baseId=" + baseId + "]";
  15. }
  16.  
  17. }
 

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

 
  1. package com.tang.janino.obj;
  2.  
  3. public class DerivedClass extends BaseClass {
  4.  
  5. private String name;
  6.  
  7. public DerivedClass(String baseId, String name) {
  8. super(baseId);
  9. this.name = name;
  10. }
  11.  
  12. @Override
  13. public String toString() {
  14. return super.toString() + "DerivedClass [name=" + name + "]";
  15. }
  16.  
  17. }
 

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

 
  1. import org.codehaus.commons.compiler.IScriptEvaluator;
  2. import org.codehaus.janino.ScriptEvaluator;
  3.  
  4. public class JaninoTester07 {
  5.  
  6. public static void main(String[] args) {
  7. try {
  8. IScriptEvaluator se = new ScriptEvaluator();
  9. se.setReturnType(String.class);
  10. se.cook("import com.tang.janino.obj.BaseClass;\n"
  11. + "import com.tang.janino.obj.DerivedClass;\n"
  12. + "BaseClass o=new DerivedClass(\"1\",\"join\");\n"
  13. + "return o.toString();\n");
  14. Object res = se.evaluate(new Object[0]);
  15. System.out.println(res);
  16. } catch (Exception e) {
  17. e.printStackTrace();
  18. }
  19. }
  20.  
  21. }
 

四、其他用法

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

2、http://janino.unkrig.de/samples/ScriptDemo.java

 

posted @ 2024-07-02 13:42  CharyGao  阅读(180)  评论(0编辑  收藏  举报