前言:學(xué)習(xí)時(shí),往往先理論后實(shí)踐纠永;工作中鬓长,往往先上手后理論。
??說(shuō)明:這里以Demo形式快速介紹Janino使用尝江,個(gè)人感覺(jué)Janino相比其它動(dòng)態(tài)編譯技術(shù)小巧涉波、高效、易上手炭序。官方介紹 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不僅支持源文件的動(dòng)態(tài)編譯啤覆、而且還支持表達(dá)式、語(yǔ)句塊惭聂、腳 本窗声、class body等動(dòng)態(tài)編譯,這使工作中選擇有了更多的余地辜纲,本文以class body為例笨觅。相關(guān)參考鏈接http://janino-compiler.github.io/janino/#janino-as-a-code-manipulator
1拦耐、工程描述
??這里是基于spring boot寫(xiě)的一個(gè)小demo,里面就三個(gè)核心的文件见剩,EacProxy.java:定義核心接口杀糯,EacProxy.temp:定義了一個(gè)模板,Janio.java:模擬業(yè)務(wù)層(對(duì)外提供接口)苍苞。
2固翰、代碼步驟
第一:配置依賴包
<dependency>
<groupId>org.codehaus.janino</groupId>
<artifactId>janino</artifactId>
<version>3.0.6</version>
</dependency>
第二:定義接口
public interface EacProxy {
public String query(); //可以返回復(fù)雜對(duì)象類型
}
第三:定義模板(所有關(guān)聯(lián)依賴的包,都要在模板中引用進(jìn)來(lái))
import com.janino.dao.EacProxy ;
public static EacProxy createProxy() {
#replaced#
}
第四:模擬業(yè)務(wù)接口
private static Map<String, String> map = new HashMap<String, String>();
static {
//用map模擬存儲(chǔ)的腳本柒啤,腳本可以是很復(fù)雜倦挂,這里只作簡(jiǎn)單測(cè)試
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 \"菜鳥(niǎo)物流下沙分倉(cāng)庫(kù)\"; }};");
}
@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語(yǔ)句塊中的map對(duì)象是用來(lái)模擬需要?jiǎng)討B(tài)執(zhí)行的class body代碼,實(shí)際開(kāi)發(fā)中這部分代碼可能是放到數(shù)據(jù)庫(kù)担巩、文本文件方援、nosql等可以動(dòng)態(tài)編輯的地方,里面可以包含復(fù)雜的邏輯涛癌,這里只模擬最簡(jiǎn)單的流程犯戏。
第五:查看執(zhí)行結(jié)果
可以多刷新幾次,會(huì)返回不同腳本的執(zhí)行結(jié)果拳话。
3先匪、打包下載
鏈接:https://pan.baidu.com/s/110_jGp5mzkyFfmqTIp6egw
提取碼:sn8s
??若鏈接莫名失效,可以留言聯(lián)系弃衍,也可以按照上述的方式自行配置呀非。