编译原理码农十年

Java之动态编译器Janino

2019-08-17  本文已影响0人  清风_gary_明月

前言:学习时,往往先理论后实践;工作中,往往先上手后理论。


  说明:这里以Demo形式快速介绍Janino使用,个人感觉Janino相比其它动态编译技术小巧、高效、易上手。官方介绍 Janino is a super-small, super-fast Java compiler.but also compile a Java expression, a block, a class body, one .java file or a set of .java files in memory, load the bytecode and execute it directly in the same JVM. Janino不仅支持源文件的动态编译、而且还支持表达式、语句块、脚 本、class body等动态编译,这使工作中选择有了更多的余地,本文以class body为例。相关参考链接http://janino-compiler.github.io/janino/#janino-as-a-code-manipulator


1、工程描述


QQ图片20190817164927.png

  这里是基于spring boot写的一个小demo,里面就三个核心的文件,EacProxy.java:定义核心接口,EacProxy.temp:定义了一个模板,Janio.java:模拟业务层(对外提供接口)。


2、代码步骤


第一:配置依赖包

<dependency>
    <groupId>org.codehaus.janino</groupId>
    <artifactId>janino</artifactId>
    <version>3.0.6</version>
</dependency>

第二:定义接口

public interface EacProxy {
     public String query();  //可以返回复杂对象类型
}

第三:定义模板(所有关联依赖的包,都要在模板中引用进来)

import com.janino.dao.EacProxy ;
public static EacProxy createProxy() {
#replaced#
}

第四:模拟业务接口

private static Map<String, String> map = new HashMap<String, String>();
    static {
        //用map模拟存储的脚本,脚本可以是很复杂,这里只作简单测试
        map.put("0", "return new EacProxy(){    public String query(){      return \"xxx交通管理局子公司分部一\";  }};");
        map.put("1", "return new EacProxy(){    public String query(){      return \"sss交通管理局子公司分部二\";  }};");
        map.put("2", "return new EacProxy(){    public String query(){      return \"阿里杭州萧山一公司\";   }};");
        map.put("3", "return new EacProxy(){    public String query(){      return \"菜鸟物流下沙分仓库\";   }};");
    }

    @RequestMapping("/janino")
    public String sayHello() throws Exception { 
        ClassBodyEvaluator ce = new ClassBodyEvaluator();//class body
        String key = String.valueOf(new Random().nextInt(4));
        String source = generateProxySource(map.get(key));
        ce.cook(source);
        Object obj = ce.getClazz().getMethod("createProxy").invoke(null);
        EacProxy ep = (EacProxy) obj;
        return ep.query();
    }

    public static String generateProxySource(String source) throws IOException {
        String template = StreamUtils.copyToString(Janino.class.getResourceAsStream("/EacProxy.temp"),
                Charset.forName("utf-8"));
        return template.replaceAll("#replaced#", source);
    }

  这里static语句块中的map对象是用来模拟需要动态执行的class body代码,实际开发中这部分代码可能是放到数据库、文本文件、nosql等可以动态编辑的地方,里面可以包含复杂的逻辑,这里只模拟最简单的流程。

第五:查看执行结果


QQ图片20190817170641.png

可以多刷新几次,会返回不同脚本的执行结果。


3、打包下载


链接:https://pan.baidu.com/s/110_jGp5mzkyFfmqTIp6egw 
提取码:sn8s 

  若链接莫名失效,可以留言联系,也可以按照上述的方式自行配置。


更多可以关注
上一篇下一篇

猜你喜欢

热点阅读