Groovy入门


参照:https://juejin.cn/post/6954350461818421278#heading-1

1. 编写 Groovy 逻辑的两种风格

  • 脚本(不定义和.groovy文件同名的class)
  • 类(定义class,所有代码都在class里)

  在 .groovy 文件内,可以不声明任何类而直接在文件顶级层次编写代码逻辑 (笔者刚才就是这样做的)。不过这样的话,就不能在文件的顶级层次再声明一个和文件同名的类,否则编译器会给出 there is a synthetic class generated for script code 的错误。从编译角度来看这可以理解,因为 .groovy 文件被编译成 .class 文件并执行时,编译器实际上会为其生成一个合成类,而正是这一步导致了冲突发生:我们刚定义的类名和它重复了。  

  实际上,如果 .groovy 文件内部出现了和文件同名的类,则意味着这个 .groovy 文件会被视作是一段 "用 Groovy 方言编写的 Java 代码",一般它也就不再作为脚本使用,而是变成一个 "普通的类" ( IDEA 称它是一个 Groovy Class) 。这么做的一个直接后果是,我们不能够在文件的顶级层次直接编写代码逻辑。

2. Java集成groovy之GroovyShell、GroovyScriptEngine、GroovyClassLoader

 https://www.cnblogs.com/jsersudo/p/10178407.html

  • GroovyClassLoader

用 Groovy 的 GroovyClassLoader ,动态地加载一个脚本并执行它的行为。GroovyClassLoader是一个定制的类装载器,
负责解释加载Java类中用到的Groovy类。

  • GroovyShell

GroovyShell允许在Java类中(甚至Groovy类)求任意Groovy表达式的值。您可使用Binding对象输入参数给表达式,
并最终通过GroovyShell返回Groovy表达式的计算结果。

  • GroovyScriptEngine

GroovyShell多用于推求对立的脚本或表达式,如果换成相互关联的多个脚本,使用GroovyScriptEngine会更好些。
GroovyScriptEngine从您指定的位置(文件系统,URL,数据库,等等)加载Groovy脚本,并且随着脚本变化而重新加载它们。
如同GroovyShell一样,GroovyScriptEngine也允许您传入参数值,并能返回脚本的值

2.1 GroovyClassLoader

 1 package groovy;
 2 
 3 import groovy.lang.Binding;
 4 import groovy.lang.GroovyShell;
 5 import groovy.lang.Script;
 6 
 7 public class TestScript {
 8     public static void main(String[] args) {
 9 
10         GroovyShell groovyShell = new GroovyShell();
11         /**
12          * 脚本为
13          def customConcat(def str1, def str2) {
14             str1.concat(str2)
15          }
16          */
17         Script scrpt = groovyShell.parse("\n" +
18                 "def customConcat(def str1, def str2) {\n" +
19                 "str1.concat(str2)\n" +
20                 "}");
21 
22         Binding binding = new Binding();
23         binding.setVariable("str1", "value1");
24         binding.setVariable("str2", "value2");
25         // binding.setVariable("newConcat", scrpt);
26 
27         scrpt.setBinding(binding);
28         System.out.println(scrpt.evaluate("str1.concat(str2)"));
29 
30         // 会抛异常
31         // Exception in thread "main" groovy.lang.MissingMethodException: No signature of method: Script1.customConcat() is applicable for argument types: (java.lang.String, java.lang.String) values: [value1, value2]
32         //    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:58)
33         //    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:81)
34         //    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:52)
35         //    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:154)
36         //    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:174)
37         //    at Script1.run(Script1.groovy:1)
38         System.out.println(scrpt.evaluate("customConcat(str1, str2)"));  // 会抛异常
39 
40         // 这种调用evaluate()执行脚本方法行不通是因没有脚本里定义的方法没有绑定,因此可以把script绑定给binding,然后执行的binding的引用方法:
41         System.out.println(scrpt.evaluate("newConcat.customConcat(str1, str2)"));    // 解开第25行注释就并且改为这样子,就不会抛异常
42     }
43 }

2.2 GroovyShell