Java之动态编译器Janino

本文通过SpringBoot项目,以classbody动态编译为切入点,详细介绍Janino的配置与使用。从依赖包引入到接口定义,再到模板创建及业务接口模拟,最后展示执行结果。

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


  说明:这里以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 

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值