前言:學(xué)習(xí)時,往往先理論后實踐;工作中,往往先上手后理論。
??說明:這里以Demo形式快速介紹Janino使用,個人感覺Janino相比其它動態(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不僅支持源文件的動態(tài)編譯、而且還支持表達(dá)式、語句塊、腳 本、class body等動態(tài)編譯,這使工作中選擇有了更多的余地,本文以class body為例。相關(guān)參考鏈接http://janino-compiler.github.io/janino/#janino-as-a-code-manipulator
1、工程描述

??這里是基于spring boot寫的一個小demo,里面就三個核心的文件,EacProxy.java:定義核心接口,EacProxy.temp:定義了一個模板,Janio.java:模擬業(yè)務(wù)層(對外提供接口)。
2、代碼步驟
第一:配置依賴包
<dependency>
<groupId>org.codehaus.janino</groupId>
<artifactId>janino</artifactId>
<version>3.0.6</version>
</dependency>
第二:定義接口
public interface EacProxy {
public String query(); //可以返回復(fù)雜對象類型
}
第三:定義模板(所有關(guān)聯(lián)依賴的包,都要在模板中引用進(jìn)來)
import com.janino.dao.EacProxy ;
public static EacProxy createProxy() {
#replaced#
}
第四:模擬業(yè)務(wù)接口
private static Map<String, String> map = new HashMap<String, String>();
static {
//用map模擬存儲的腳本,腳本可以是很復(fù)雜,這里只作簡單測試
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對象是用來模擬需要動態(tài)執(zhí)行的class body代碼,實際開發(fā)中這部分代碼可能是放到數(shù)據(jù)庫、文本文件、nosql等可以動態(tài)編輯的地方,里面可以包含復(fù)雜的邏輯,這里只模擬最簡單的流程。
第五:查看執(zhí)行結(jié)果

可以多刷新幾次,會返回不同腳本的執(zhí)行結(jié)果。
3、打包下載
鏈接:https://pan.baidu.com/s/110_jGp5mzkyFfmqTIp6egw
提取碼:sn8s
??若鏈接莫名失效,可以留言聯(lián)系,也可以按照上述的方式自行配置。
