Java中使用Groovy的三种方式

使用GroovyShell执行groovy脚本

pom.xml中依赖

    
      org.codehaus.groovy
      groovy-all
      3.0.9
    

evaluate方法执行groovy片段

调用evaluate方法直接执行一段Groovy
public static void testGroovy1() throws CompilationFailedException, IOException {
	GroovyShell groovyShell = new GroovyShell();
	groovyShell.evaluate("println 'My First Groovy shell.'");
}

原理(源码)解析

步骤:生成一个GroovyCodeSource(脚本及脚本信息)-》GroovyClassLoader
1、
public Object evaluate(String scriptText) throws CompilationFailedException {
        return this.evaluate(scriptText, this.generateScriptName(), "/groovy/shell");
}
//scriptText:groovy语句
//this.generateScriptName():生成一个默认的groovy脚本名称
//"/groovy/shell":默认值,用于java的安全管理器
2、
public Object evaluate(String scriptText, String fileName, String codeBase) throws CompilationFailedException {
    SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
        sm.checkPermission(new GroovyCodeSourcePermission(codeBase));
    }
	//安全管理
    GroovyCodeSource gcs = (GroovyCodeSource)AccessController.doPrivileged(() -> {
        return new GroovyCodeSource(scriptText, fileName, codeBase);
    });
    //构建GroovyCodeSource
    return this.evaluate(gcs);
}
3、
public Object evaluate(GroovyCodeSource codeSource) throws CompilationFailedException {
    //解析groovy脚本
    Script script = this.parse(codeSource);
    //运行脚本
    return script.run();
}
4、
public Script parse(GroovyCodeSource codeSource) throws CompilationFailedException {
    return InvokerHelper.createScript(this.parseClass(codeSource), this.context);
}
5、类加载 GroovyClassLoader
private Class parseClass(GroovyCodeSource codeSource) throws CompilationFailedException {
    return this.loader.parseClass(codeSource, false);
}
6、是否使用缓存

public Class parseClass(GroovyCodeSource codeSource, boolean shouldCacheSource) throws CompilationFailedException {
    String cacheKey = this.genSourceCacheKey(codeSource);
    return (Class)this.sourceCache.getAndPut(cacheKey, (key) -> {
        return this.doParseClass(codeSource);
    }, shouldCacheSource);
}
7、

private Class doParseClass(GroovyCodeSource codeSource) {
    validate(codeSource);
    //创建编译单元
    CompilationUnit unit = this.createCompilationUnit(this.config, codeSource.getCodeSource());
    if (this.recompile != null && this.recompile || this.recompile == null && this.config.getRecompileGroovySource()) {
        unit.addFirstPhaseOperation(GroovyClassLoader.TimestampAdder.INSTANCE, CompilePhase.CLASS_GENERATION.getPhaseNumber());
	}
    //资源单元
    SourceUnit su;
    ...
    //
	GroovyClassLoader.ClassCollector collector = this.createCollector(unit, su);
    unit.setClassgenCallback(collector);
    ...
    //编译
    unit.compile(goalPhase);
    Class answer = collector.generatedClass;
    String mainClass = su.getAST().getMainClassName();
    Iterator var9 = collector.getLoadedClasses().iterator();

    while(var9.hasNext()) {
        Object o = var9.next();
        Class clazz = (Class)o;
        String clazzName = clazz.getName();
        this.definePackageInternal(clazzName);
        this.setClassCacheEntry(clazz);
        if (clazzName.equals(mainClass)) {
            answer = clazz;
        }
    }

    return answer;    
       
}
7.5创建类采集器
protected GroovyClassLoader.ClassCollector createCollector(CompilationUnit unit, SourceUnit su) {
    GroovyClassLoader.InnerLoader loader = (GroovyClassLoader.InnerLoader)AccessController.doPrivileged(() -> {
        return new GroovyClassLoader.InnerLoader(this);
    });
    return new GroovyClassLoader.ClassCollector(loader, unit, su);
}

执行groovy文件(无输入参数)

groovy文件

// 不带参数的groovy方法
def sayHello() {
	println 'Hello World.'
	// 如果不写return, groovy方法的默认最后一行为 方法的返回值
	//return "GroovyShell_1中的sayHello()方法的返回值"
	"GroovyShell_1中的sayHello()方法的返回值"
}
// 运行groovy方法
sayHello()

java方法

// 调用GroovyShell_1_1文件
public static void testGroovy2() throws CompilationFailedException, IOException {
	GroovyShell groovyShell = new GroovyShell();
	Object result = groovyShell.evaluate(new File("src/main/java/com/juxinli/groovy/GroovyShell_1_1.groovy"));
	logger.info(result.toString());//result 为groovy脚本的返回值
}

原理解析

//与上同理,只是将文件中的内容读取成指定类

执行groovy文件(有输入参数)

groovy文件

// 带参数的groovy方法
def sayHello(name) {
	println "Hello " + name + "."
	// 如果不写return, groovy方法的默认最后一行为 方法的返回值
	//return "GroovyShell_1中的sayHello()方法的返回值"
	"GroovyShell_1中的sayHello(name)方法的返回值"
}
// 运行groovy方法
sayHello(name)

java方法

// 调用GroovyShell_1_2
public static void testGroovy3() throws CompilationFailedException, IOException {
	// 调用带参数的groovy shell时,使用bind绑定数据
	Binding binding = new Binding();
	binding.setProperty("name", "Juxinli");	//用Binding类绑定参数
	GroovyShell groovyShell = new GroovyShell(binding);//执行groovy文件时,传入Binging类
	Object result = groovyShell.evaluate(new File("src/main/java/com/juxinli/groovy/GroovyShell_1_2.groovy"));
	logger.info(result.toString());
}

原理解析

//输入参数是GroovyShell中的属性context的属性
public class GroovyShell extends GroovyObjectSupport {
    private final Binding context;
        public GroovyShell(Binding binding) {
        this((ClassLoader)null, (Binding)binding);
    }
    ...
}
//执行脚本 groovyShell.evaluate(groovy文件)
//this.context为输入参数
public Script parse(GroovyCodeSource codeSource) throws CompilationFailedException {
    return InvokerHelper.createScript(this.parseClass(codeSource), this.context);
}
//将Binding的输入参数与main方法中的输入参数绑定
public static Script createScript(Class scriptClass, Binding context) {
    ...
    Object args = this.getProperty("args");
    object.invokeMethod("main", argsToPass);
    ...
}

groovy文件编译为字节码(class文件)

IDEA中可以直接运行groovy文件,将.groovy文件可以编译为.class文件

如:GroovyTest.groovy

package com.jsq.groovy

class GroovyTest {
    static main(args) {
        println "hello world"
    }
}

编译后的字节码:GroovyTest.class

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.jsq.groovy;

import groovy.lang.GroovyObject;
import groovy.lang.MetaClass;
import groovy.transform.Generated;
import groovy.transform.Internal;
import java.beans.Transient;
import org.codehaus.groovy.runtime.callsite.CallSite;

public class GroovyTest implements GroovyObject {
    @Generated
    public GroovyTest() {
        CallSite[] var1 = $getCallSiteArray();
        super();
        MetaClass var2 = this.$getStaticMetaClass();
        this.metaClass = var2;
    }

    public static void main(String... args) {
        CallSite[] var1 = $getCallSiteArray();
        var1[0].callStatic(GroovyTest.class, "hello world");
    }

    @Generated
    @Internal
    @Transient
    public MetaClass getMetaClass() {
        MetaClass var10000 = this.metaClass;
        if (var10000 != null) {
            return var10000;
        } else {
            this.metaClass = this.$getStaticMetaClass();
            return this.metaClass;
        }
    }

    @Generated
    @Internal
    public void setMetaClass(MetaClass var1) {
        this.metaClass = var1;
    }
}

你可能感兴趣的:(Java,java)