Java之动态编译器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
若链接莫名失效,可以留言联系,也可以按照上述的方式自行配置。
更多可以关注