10、Groovy实现代码热载的机制和原理

10、Groovy实现代码热载的机制和原理

我们知道,Groovy在很大一部分的用途是在java工程里面穿插使用的,本文的主题是Groovy实现代码热载,,其他大背景是java实现主干代码,,groovy实现易变动的逻辑代码. 先来看下java是如何调用的groovy脚本的。

Groovy代码热载例子

import groovy.lang.Binding;
import groovy.lang.GroovyShell;
 
public class GroovyTest {
 
    public static void main(String[] args) {
        // *) groovy 代码
        String script = "println 'hello'; 'name = ' + name;";
 
        // *) 传入参数
        Binding binding = new Binding();
        binding.setVariable("name", "lilei");
 
        // *) 执行脚本代码
        GroovyShell shell = new GroovyShell(binding);
        Object res = shell.evaluate(script);
        System.out.println(res);
    }
}

这个例子的输出结果即为其中groovy代码的输出结果:
10、Groovy实现代码热载的机制和原理
接下来我们来分析一下传入参数和执行脚本代码的源码。

//groovy.lang.binding

//一个收集参数的map属性
private Map variables;

    public Binding() {
    }
	//构造函数
    public Binding(Map variables) {
        this.variables = variables;
    }

    public Binding(String[] args) {
        this();
        this.setVariable("args", args);
    }
	//余下的是对参数数据map的一些操作,就不列出来了

所以Binging里面其实就是用一个map存储其传来的参数而已,我们再来看GroovyShell类,对于其中的函数evaluate, 我们追踪进去, 会有不少的新认识。

  public Object evaluate(GroovyCodeSource codeSource) throws CompilationFailedException {
        Script script = this.parse(codeSource);
        return script.run();
    }
 
    public Script parse(GroovyCodeSource codeSource) throws CompilationFailedException {
        return InvokerHelper.createScript(this.parseClass(codeSource), this.context);
    }

其大致的思路, 为Groovy脚本代码包装生成class, 然后产生该类实例对象, 在具体执行其包装的逻辑代码。而在parse方法的parseClass源码如下所示:

 public Class parseClass(String text) throws CompilationFailedException {
        return this.parseClass(text, "script" + System.currentTimeMillis() + Math.abs(text.hashCode()) + ".groovy");
    }

对于groovy脚本, 它默认会生成名字为script + System.currentTimeMillis() + Math.abs(text.hashCode())的class类, 也就是说传入脚本, 它都会生成一个新类, 就算同一段groovy脚本代码, 每调用一次, 都会生成一个新类。

总结

对于Groovy脚本,先用Binding传入参数到map数组里面,再根据Binding创建GroovyShell对象, 然后为Groovy脚本代码包装生成class, 然后产生该类实例对象, 在具体执行其包装的逻辑代码。而在parse方法的parseClass源码如下所示。

上一篇:很随便的JS笔记2


下一篇:php 获取当前目录和当前文件夹